OpenTTD Source: src/network/network_client.cpp Source File

OpenTTD Source 15.0-RC2

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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
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
43 struct PacketReader : LoadFilter {
44 using Buffer = std::deque<uint8_t>;
45
46 Buffer buffer;
47 Buffer::const_iterator iterator;
48 size_t read_bytes = 0;
49
51 PacketReader() : LoadFilter(nullptr)
52 {
53 }
54
59 void AddPacket(Packet &p)
60 {
61 assert(this->read_bytes == 0);
62 p.TransferOut([this](std::span<const uint8_t> source) {
63 std::ranges::copy(source, std::back_inserter(this->buffer));
64 return source.size();
65 });
66 }
67
68 size_t Read(uint8_t *rbuf, size_t size) override
69 {
70 /* Limit the amount to read to whatever we still have. */
71 size_t read_size = std::min(this->buffer.size() - this->read_bytes, size);
72
73 std::copy_n(this->iterator, read_size, rbuf);
74 std::advance(this->iterator, read_size);
75 this->read_bytes += read_size;
76
77 return read_size;
78 }
79
80 void Reset() override
81 {
82 this->read_bytes = 0;
83 this->iterator = this->buffer.cbegin();
84 }
85};
86
87
91 void ClientNetworkEmergencySave()
92{
93 static FiosNumberedSaveName _netsave_ctr("netsave");
94 DoAutoOrNetsave(_netsave_ctr);
95}
96
97
102ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, std::string_view connection_string) : NetworkGameSocketHandler(s), connection_string(connection_string)
103{
104 assert(ClientNetworkGameSocketHandler::my_client == nullptr);
105 ClientNetworkGameSocketHandler::my_client = this;
106}
107
109ClientNetworkGameSocketHandler::~ClientNetworkGameSocketHandler()
110{
111 assert(ClientNetworkGameSocketHandler::my_client == this);
112 ClientNetworkGameSocketHandler::my_client = nullptr;
113
114 delete this->GetInfo();
115}
116
117 NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
118{
119 assert(status != NETWORK_RECV_STATUS_OKAY);
120 if (this->IsPendingDeletion()) return status;
121
122 assert(this->sock != INVALID_SOCKET);
123
124 if (!this->HasClientQuit()) {
125 Debug(net, 3, "Closed client connection {}", this->client_id);
126
127 this->SendPackets(true);
128
129 /* Wait a number of ticks so our leave message can reach the server.
130 * This is especially needed for Windows servers as they seem to get
131 * the "socket is closed" message before receiving our leave message,
132 * which would trigger the server to close the connection as well. */
133 CSleep(3 * MILLISECONDS_PER_TICK);
134 }
135
136 this->DeferDeletion();
137
138 return status;
139}
140
145 void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
146{
147 if (this->IsPendingDeletion()) return;
148
149 /* First, send a CLIENT_ERROR to the server, so it knows we are
150 * disconnected (and why!) */
151 NetworkErrorCode errorno;
152
153 /* We just want to close the connection.. */
154 if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
155 this->NetworkSocketHandler::MarkClosed();
156 this->CloseConnection(res);
157 _networking = false;
158
159 CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
160 return;
161 }
162
163 switch (res) {
164 case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
165 case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
166 case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
167 default: errorno = NETWORK_ERROR_GENERAL; break;
168 }
169
170 if (res == NETWORK_RECV_STATUS_SERVER_ERROR || res == NETWORK_RECV_STATUS_SERVER_FULL ||
171 res == NETWORK_RECV_STATUS_SERVER_BANNED) {
172 /* This means the server closed the connection. Emergency save is
173 * already created if this was appropriate during handling of the
174 * disconnect. */
175 this->CloseConnection(res);
176 } else {
177 /* This means we as client made a boo-boo. */
178 SendError(errorno);
179
180 /* Close connection before we make an emergency save, as the save can
181 * take a bit of time; better that the server doesn't stall while we
182 * are doing the save, and already disconnects us. */
183 this->CloseConnection(res);
184 ClientNetworkEmergencySave();
185 }
186
187 CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
188
189 if (_game_mode != GM_MENU) _switch_mode = SM_MENU;
190 _networking = false;
191}
192
193
199/* static */ bool ClientNetworkGameSocketHandler::Receive()
200{
201 if (my_client->CanSendReceive()) {
202 NetworkRecvStatus res = my_client->ReceivePackets();
203 if (res != NETWORK_RECV_STATUS_OKAY) {
204 /* The client made an error of which we can not recover.
205 * Close the connection and drop back to the main menu. */
206 my_client->ClientError(res);
207 return false;
208 }
209 }
210 return _networking;
211}
212
214/* static */ void ClientNetworkGameSocketHandler::Send()
215{
216 my_client->SendPackets();
217 if (my_client != nullptr) my_client->CheckConnection();
218}
219
224/* static */ bool ClientNetworkGameSocketHandler::GameLoop()
225{
226 _frame_counter++;
227
228 NetworkExecuteLocalCommandQueue();
229
230 StateGameLoop();
231
232 /* Check if we are in sync! */
233 if (_sync_frame != 0) {
234 if (_sync_frame == _frame_counter) {
235#ifdef NETWORK_SEND_DOUBLE_SEED
236 if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
237#else
238 if (_sync_seed_1 != _random.state[0]) {
239#endif
240 ShowNetworkError(STR_NETWORK_ERROR_DESYNC);
241 Debug(desync, 1, "sync_err: {:08x}; {:02x}", TimerGameEconomy::date, TimerGameEconomy::date_fract);
242 Debug(net, 0, "Sync error detected");
243 my_client->ClientError(NETWORK_RECV_STATUS_DESYNC);
244 return false;
245 }
246
247 /* If this is the first time we have a sync-frame, we
248 * need to let the server know that we are ready and at the same
249 * frame as it is.. so we can start playing! */
250 if (_network_first_time) {
251 _network_first_time = false;
252 SendAck();
253 }
254
255 _sync_frame = 0;
256 } else if (_sync_frame < _frame_counter) {
257 Debug(net, 1, "Missed frame for sync-test: {} / {}", _sync_frame, _frame_counter);
258 _sync_frame = 0;
259 }
260 }
261
262 return true;
263}
264
265
267 ClientNetworkGameSocketHandler * ClientNetworkGameSocketHandler::my_client = nullptr;
268
270 static uint32_t last_ack_frame;
271
273 static uint8_t _network_server_max_companies;
275std::string _network_server_name;
276
278 NetworkJoinInfo _network_join;
279
280/***********
281 * Sending functions
282 ************/
283
285 NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin()
286{
287 Debug(net, 9, "Client::SendJoin()");
288
289 Debug(net, 9, "Client::status = JOIN");
290 my_client->status = STATUS_JOIN;
291 Debug(net, 9, "Client::join_status = AUTHORIZING");
292 _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
293 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
294
295 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_JOIN);
296 p->Send_string(GetNetworkRevisionString());
297 p->Send_uint32(_openttd_newgrf_version);
298 my_client->SendPacket(std::move(p));
299
300 return NETWORK_RECV_STATUS_OKAY;
301}
302
303 NetworkRecvStatus ClientNetworkGameSocketHandler::SendIdentify()
304{
305 Debug(net, 9, "Client::SendIdentify()");
306
307 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_IDENTIFY);
308 p->Send_string(_settings_client.network.client_name); // Client name
309 p->Send_uint8(_network_join.company); // PlayAs
310 my_client->SendPacket(std::move(p));
311 return NETWORK_RECV_STATUS_OKAY;
312}
313
315 NetworkRecvStatus ClientNetworkGameSocketHandler::SendNewGRFsOk()
316{
317 Debug(net, 9, "Client::SendNewGRFsOk()");
318
319 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_NEWGRFS_CHECKED);
320 my_client->SendPacket(std::move(p));
321 return NETWORK_RECV_STATUS_OKAY;
322}
323
328 NetworkRecvStatus ClientNetworkGameSocketHandler::SendAuthResponse()
329{
330 Debug(net, 9, "Client::SendAuthResponse()");
331
332 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_AUTH_RESPONSE);
333 my_client->authentication_handler->SendResponse(*p);
334 my_client->SendPacket(std::move(p));
335
336 return NETWORK_RECV_STATUS_OKAY;
337}
338
340 NetworkRecvStatus ClientNetworkGameSocketHandler::SendGetMap()
341{
342 Debug(net, 9, "Client::SendGetMap()");
343
344 Debug(net, 9, "Client::status = MAP_WAIT");
345 my_client->status = STATUS_MAP_WAIT;
346
347 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_GETMAP);
348 my_client->SendPacket(std::move(p));
349 return NETWORK_RECV_STATUS_OKAY;
350}
351
353 NetworkRecvStatus ClientNetworkGameSocketHandler::SendMapOk()
354{
355 Debug(net, 9, "Client::SendMapOk()");
356
357 Debug(net, 9, "Client::status = ACTIVE");
358 my_client->status = STATUS_ACTIVE;
359
360 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_MAP_OK);
361 my_client->SendPacket(std::move(p));
362 return NETWORK_RECV_STATUS_OKAY;
363}
364
366 NetworkRecvStatus ClientNetworkGameSocketHandler::SendAck()
367{
368 Debug(net, 9, "Client::SendAck()");
369
370 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_ACK);
371
372 p->Send_uint32(_frame_counter);
373 p->Send_uint8 (my_client->token);
374 my_client->SendPacket(std::move(p));
375 return NETWORK_RECV_STATUS_OKAY;
376}
377
382 NetworkRecvStatus ClientNetworkGameSocketHandler::SendCommand(const CommandPacket &cp)
383{
384 Debug(net, 9, "Client::SendCommand(): cmd={}", cp.cmd);
385
386 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_COMMAND);
387 my_client->NetworkGameSocketHandler::SendCommand(*p, cp);
388
389 my_client->SendPacket(std::move(p));
390 return NETWORK_RECV_STATUS_OKAY;
391}
392
394 NetworkRecvStatus ClientNetworkGameSocketHandler::SendChat(NetworkAction action, DestType type, int dest, std::string_view msg, int64_t data)
395{
396 Debug(net, 9, "Client::SendChat(): action={}, type={}, dest={}", action, type, dest);
397
398 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_CHAT);
399
400 p->Send_uint8 (action);
401 p->Send_uint8 (type);
402 p->Send_uint32(dest);
403 p->Send_string(msg);
404 p->Send_uint64(data);
405
406 my_client->SendPacket(std::move(p));
407 return NETWORK_RECV_STATUS_OKAY;
408}
409
411 NetworkRecvStatus ClientNetworkGameSocketHandler::SendError(NetworkErrorCode errorno)
412{
413 Debug(net, 9, "Client::SendError(): errorno={}", errorno);
414
415 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_ERROR);
416
417 p->Send_uint8(errorno);
418 my_client->SendPacket(std::move(p));
419 return NETWORK_RECV_STATUS_OKAY;
420}
421
426 NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetName(const std::string &name)
427{
428 Debug(net, 9, "Client::SendSetName()");
429
430 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_SET_NAME);
431
432 p->Send_string(name);
433 my_client->SendPacket(std::move(p));
434 return NETWORK_RECV_STATUS_OKAY;
435}
436
440 NetworkRecvStatus ClientNetworkGameSocketHandler::SendQuit()
441{
442 Debug(net, 9, "Client::SendQuit()");
443
444 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_QUIT);
445
446 my_client->SendPacket(std::move(p));
447 return NETWORK_RECV_STATUS_OKAY;
448}
449
455 NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(std::string_view pass, std::string_view command)
456{
457 Debug(net, 9, "Client::SendRCon()");
458
459 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_RCON);
460 p->Send_string(pass);
461 p->Send_string(command);
462 my_client->SendPacket(std::move(p));
463 return NETWORK_RECV_STATUS_OKAY;
464}
465
470 NetworkRecvStatus ClientNetworkGameSocketHandler::SendMove(CompanyID company)
471{
472 Debug(net, 9, "Client::SendMove(): company={}", company);
473
474 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_MOVE);
475 p->Send_uint8(company);
476 my_client->SendPacket(std::move(p));
477 return NETWORK_RECV_STATUS_OKAY;
478}
479
484 bool ClientNetworkGameSocketHandler::IsConnected()
485{
486 return my_client != nullptr && my_client->status == STATUS_ACTIVE;
487}
488
489
490/***********
491 * Receiving functions
492 ************/
493
494extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, std::shared_ptr<struct LoadFilter> lf);
495
496 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet &)
497{
498 Debug(net, 9, "Client::Receive_SERVER_FULL()");
499
500 /* We try to join a server which is full */
501 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SERVER_FULL), {}, WL_CRITICAL);
502
503 return NETWORK_RECV_STATUS_SERVER_FULL;
504}
505
506 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet &)
507{
508 Debug(net, 9, "Client::Receive_SERVER_BANNED()");
509
510 /* We try to join a server where we are banned */
511 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SERVER_BANNED), {}, WL_CRITICAL);
512
513 return NETWORK_RECV_STATUS_SERVER_BANNED;
514}
515
516/* This packet contains info about the client (playas and name)
517 * as client we save this in NetworkClientInfo, linked via 'client_id'
518 * which is always an unique number on a server. */
519 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet &p)
520{
521 NetworkClientInfo *ci;
522 ClientID client_id = (ClientID)p.Recv_uint32();
523 CompanyID playas = (CompanyID)p.Recv_uint8();
524
525 Debug(net, 9, "Client::Receive_SERVER_CLIENT_INFO(): client_id={}, playas={}", client_id, playas);
526
527 std::string name = p.Recv_string(NETWORK_NAME_LENGTH);
528 std::string public_key = p.Recv_string(NETWORK_PUBLIC_KEY_LENGTH);
529
530 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
531 if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
532 /* The server validates the name when receiving it from clients, so when it is wrong
533 * here something went really wrong. In the best case the packet got malformed on its
534 * way too us, in the worst case the server is broken or compromised. */
535 if (!NetworkIsValidClientName(name)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
536
537 ci = NetworkClientInfo::GetByClientID(client_id);
538 if (ci != nullptr) {
539 if (playas == ci->client_playas && name != ci->client_name) {
540 /* Client name changed, display the change */
541 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name);
542 } else if (playas != ci->client_playas) {
543 /* The client changed from client-player..
544 * Do not display that for now */
545 }
546
547 /* Make sure we're in the company the server tells us to be in,
548 * for the rare case that we get moved while joining. */
549 if (client_id == _network_own_client_id) SetLocalCompany(!Company::IsValidID(playas) ? COMPANY_SPECTATOR : playas);
550
551 ci->client_playas = playas;
552 ci->client_name = std::move(name);
553 ci->public_key = std::move(public_key);
554
555 InvalidateWindowData(WC_CLIENT_LIST, 0);
556
557 return NETWORK_RECV_STATUS_OKAY;
558 }
559
560 /* There are at most as many ClientInfo as ClientSocket objects in a
561 * server. Having more info than a server can have means something
562 * has gone wrong somewhere, i.e. the server has more info than it
563 * has actual clients. That means the server is feeding us an invalid
564 * state. So, bail out! This server is broken. */
565 if (!NetworkClientInfo::CanAllocateItem()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
566
567 /* We don't have this client_id yet, find an empty client_id, and put the data there */
568 ci = new NetworkClientInfo(client_id);
569 ci->client_playas = playas;
570 if (client_id == _network_own_client_id) this->SetInfo(ci);
571
572 ci->client_name = std::move(name);
573 ci->public_key = std::move(public_key);
574
575 InvalidateWindowData(WC_CLIENT_LIST, 0);
576
577 return NETWORK_RECV_STATUS_OKAY;
578}
579
580 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &p)
581{
582 static const StringID network_error_strings[] = {
583 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_GENERAL
584 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_DESYNC
585 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_SAVEGAME_FAILED
586 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_CONNECTION_LOST
587 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_ILLEGAL_PACKET
588 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NEWGRF_MISMATCH
589 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_AUTHORIZED
590 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_EXPECTED
591 STR_NETWORK_ERROR_WRONG_REVISION, // NETWORK_ERROR_WRONG_REVISION
592 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NAME_IN_USE
593 STR_NETWORK_ERROR_WRONG_PASSWORD, // NETWORK_ERROR_WRONG_PASSWORD
594 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_COMPANY_MISMATCH
595 STR_NETWORK_ERROR_KICKED, // NETWORK_ERROR_KICKED
596 STR_NETWORK_ERROR_CHEATER, // NETWORK_ERROR_CHEATER
597 STR_NETWORK_ERROR_SERVER_FULL, // NETWORK_ERROR_FULL
598 STR_NETWORK_ERROR_TOO_MANY_COMMANDS, // NETWORK_ERROR_TOO_MANY_COMMANDS
599 STR_NETWORK_ERROR_TIMEOUT_PASSWORD, // NETWORK_ERROR_TIMEOUT_PASSWORD
600 STR_NETWORK_ERROR_TIMEOUT_COMPUTER, // NETWORK_ERROR_TIMEOUT_COMPUTER
601 STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
602 STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
603 STR_NETWORK_ERROR_INVALID_CLIENT_NAME, // NETWORK_ERROR_INVALID_CLIENT_NAME
604 STR_NETWORK_ERROR_NOT_ON_ALLOW_LIST, // NETWORK_ERROR_NOT_ON_ALLOW_LIST
605 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE
606 };
607 static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
608
609 NetworkErrorCode error = (NetworkErrorCode)p.Recv_uint8();
610
611 Debug(net, 9, "Client::Receive_SERVER_ERROR(): error={}", error);
612
613 StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
614 if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
615 /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
616 if (error == NETWORK_ERROR_KICKED && p.CanReadFromPacket(1)) {
617 ShowErrorMessage(GetEncodedString(err),
618 GetEncodedString(STR_NETWORK_ERROR_KICK_MESSAGE, p.Recv_string(NETWORK_CHAT_LENGTH)),
619 WL_CRITICAL);
620 } else {
621 ShowErrorMessage(GetEncodedString(err), {}, WL_CRITICAL);
622 }
623
624 /* Perform an emergency save if we had already entered the game */
625 if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
626
627 return NETWORK_RECV_STATUS_SERVER_ERROR;
628}
629
630 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(Packet &p)
631{
632 if (this->status != STATUS_ENCRYPTED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
633
634 uint grf_count = p.Recv_uint8();
635 NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
636
637 Debug(net, 9, "Client::Receive_SERVER_CHECK_NEWGRFS(): grf_count={}", grf_count);
638
639 /* Check all GRFs */
640 for (; grf_count > 0; grf_count--) {
641 GRFIdentifier c;
642 DeserializeGRFIdentifier(p, c);
643
644 /* Check whether we know this GRF */
645 const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, &c.md5sum);
646 if (f == nullptr) {
647 /* We do not know this GRF, bail out of initialization */
648 Debug(grf, 0, "NewGRF {:08X} not found; checksum {}", std::byteswap(c.grfid), FormatArrayAsHex(c.md5sum));
649 ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH;
650 }
651 }
652
653 if (ret == NETWORK_RECV_STATUS_OKAY) {
654 /* Start receiving the map */
655 return SendNewGRFsOk();
656 }
657
658 /* NewGRF mismatch, bail out */
659 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_NEWGRF_MISMATCH), {}, WL_CRITICAL);
660 return ret;
661}
662
663 class ClientGamePasswordRequestHandler : public NetworkAuthenticationPasswordRequestHandler {
664 virtual void SendResponse() override { MyClient::SendAuthResponse(); }
665 virtual void AskUserForPassword(std::shared_ptr<NetworkAuthenticationPasswordRequest> request) override
666 {
667 if (!_network_join.server_password.empty()) {
668 request->Reply(_network_join.server_password);
669 } else {
670 ShowNetworkNeedPassword(std::move(request));
671 }
672 }
673};
674
675 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_AUTH_REQUEST(Packet &p)
676{
677 if (this->status != STATUS_JOIN && this->status != STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
678 Debug(net, 9, "Client::status = AUTH_GAME");
679 this->status = STATUS_AUTH_GAME;
680
681 Debug(net, 9, "Client::Receive_SERVER_AUTH_REQUEST()");
682
683 if (this->authentication_handler == nullptr) {
684 this->authentication_handler = NetworkAuthenticationClientHandler::Create(std::make_shared<ClientGamePasswordRequestHandler>(),
685 _settings_client.network.client_secret_key, _settings_client.network.client_public_key);
686 }
687 switch (this->authentication_handler->ReceiveRequest(p)) {
688 case NetworkAuthenticationClientHandler::RequestResult::ReadyForResponse:
689 return SendAuthResponse();
690
691 case NetworkAuthenticationClientHandler::RequestResult::AwaitUserInput:
692 return NETWORK_RECV_STATUS_OKAY;
693
694 case NetworkAuthenticationClientHandler::RequestResult::Invalid:
695 default:
696 return NETWORK_RECV_STATUS_MALFORMED_PACKET;
697 }
698}
699
700 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION(Packet &p)
701{
702 if (this->status != STATUS_AUTH_GAME || this->authentication_handler == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
703
704 Debug(net, 9, "Client::Receive_SERVER_ENABLE_ENCRYPTION()");
705
706 if (!this->authentication_handler->ReceiveEnableEncryption(p)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
707
708 this->receive_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
709 this->send_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
710 this->authentication_handler = nullptr;
711
712 Debug(net, 9, "Client::status = ENCRYPTED");
713 this->status = STATUS_ENCRYPTED;
714
715 return this->SendIdentify();
716}
717
718 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet &p)
719{
720 if (this->status < STATUS_ENCRYPTED || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
721 Debug(net, 9, "Client::status = AUTHORIZED");
722 this->status = STATUS_AUTHORIZED;
723
724 _network_own_client_id = (ClientID)p.Recv_uint32();
725
726 Debug(net, 9, "Client::Receive_SERVER_WELCOME(): client_id={}", _network_own_client_id);
727
728 /* Start receiving the map */
729 return SendGetMap();
730}
731
732 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WAIT(Packet &p)
733{
734 /* We set the internal wait state when requesting the map. */
735 if (this->status != STATUS_MAP_WAIT) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
736
737 Debug(net, 9, "Client::Receive_SERVER_WAIT()");
738
739 /* But... only now we set the join status to waiting, instead of requesting. */
740 Debug(net, 9, "Client::join_status = WAITING");
741 _network_join_status = NETWORK_JOIN_STATUS_WAITING;
742 _network_join_waiting = p.Recv_uint8();
743 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
744
745 return NETWORK_RECV_STATUS_OKAY;
746}
747
748 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_BEGIN(Packet &p)
749{
750 if (this->status < STATUS_AUTHORIZED || this->status >= STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
751 Debug(net, 9, "Client::status = MAP");
752 this->status = STATUS_MAP;
753
754 if (this->savegame != nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
755
756 this->savegame = std::make_shared<PacketReader>();
757
758 _frame_counter = _frame_counter_server = _frame_counter_max = p.Recv_uint32();
759
760 Debug(net, 9, "Client::Receive_SERVER_MAP_BEGIN(): frame_counter={}", _frame_counter);
761
762 _network_join_bytes = 0;
763 _network_join_bytes_total = 0;
764
765 Debug(net, 9, "Client::join_status = DOWNLOADING");
766 _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
767 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
768
769 return NETWORK_RECV_STATUS_OKAY;
770}
771
772 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_SIZE(Packet &p)
773{
774 if (this->status != STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
775 if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
776
777 _network_join_bytes_total = p.Recv_uint32();
778 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
779
780 Debug(net, 9, "Client::Receive_SERVER_MAP_SIZE(): bytes_total={}", _network_join_bytes_total);
781
782 return NETWORK_RECV_STATUS_OKAY;
783}
784
785 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DATA(Packet &p)
786{
787 if (this->status != STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
788 if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
789
790 /* We are still receiving data, put it to the file */
791 this->savegame->AddPacket(p);
792
793 _network_join_bytes = static_cast<uint32_t>(this->savegame->buffer.size());
794 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
795
796 return NETWORK_RECV_STATUS_OKAY;
797}
798
799 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet &)
800{
801 if (this->status != STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
802 if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
803
804 Debug(net, 9, "Client::Receive_SERVER_MAP_DONE()");
805
806 Debug(net, 9, "Client::join_status = PROCESSING");
807 _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
808 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
809
810 this->savegame->Reset();
811
812 /* The map is done downloading, load it */
813 ClearErrorMessages();
814
815 /* Set the abstract filetype. This is read during savegame load. */
816 _file_to_saveload.SetMode(FIOS_TYPE_FILE, SLO_LOAD);
817
818 bool load_success = SafeLoad({}, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, this->savegame);
819 this->savegame = nullptr;
820
821 /* Long savegame loads shouldn't affect the lag calculation! */
822 this->last_packet = std::chrono::steady_clock::now();
823
824 if (!load_success) {
825 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SAVEGAMEERROR), {}, WL_CRITICAL);
826 return NETWORK_RECV_STATUS_SAVEGAME;
827 }
828 /* If the savegame has successfully loaded, ALL windows have been removed,
829 * only toolbar/statusbar and gamefield are visible */
830
831 /* Say we received the map and loaded it correctly! */
832 SendMapOk();
833
834 /* As we skipped switch-mode, update the time we "switched". */
835 _game_session_stats.start_time = std::chrono::steady_clock::now();
836 _game_session_stats.savegame_size = std::nullopt;
837
838 ShowClientList();
839
840 /* New company/spectator (invalid company) or company we want to join is not active
841 * Switch local company to spectator and await the server's judgement */
842 if (_network_join.company == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join.company)) {
843 SetLocalCompany(COMPANY_SPECTATOR);
844
845 if (_network_join.company != COMPANY_SPECTATOR) {
846 /* We have arrived and ready to start playing; send a command to make a new company;
847 * the server will give us a client-id and let us in */
848 Debug(net, 9, "Client::join_status = REGISTERING");
849 _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
850 ShowJoinStatusWindow();
851 Command<CMD_COMPANY_CTRL>::Post(CCA_NEW, CompanyID::Invalid(), CRR_NONE, _network_own_client_id);
852 }
853 } else {
854 /* take control over an existing company */
855 SetLocalCompany(_network_join.company);
856 }
857
858 SocialIntegration::EventEnterMultiplayer(Map::SizeX(), Map::SizeY());
859
860 return NETWORK_RECV_STATUS_OKAY;
861}
862
863 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FRAME(Packet &p)
864{
865 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
866
867 _frame_counter_server = p.Recv_uint32();
868 _frame_counter_max = p.Recv_uint32();
869#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
870 /* Test if the server supports this option
871 * and if we are at the frame the server is */
872#ifdef NETWORK_SEND_DOUBLE_SEED
873 if (p.CanReadFromPacket(sizeof(uint32_t) + sizeof(uint32_t))) {
874#else
875 if (p.CanReadFromPacket(sizeof(uint32_t))) {
876#endif
877 _sync_frame = _frame_counter_server;
878 _sync_seed_1 = p.Recv_uint32();
879#ifdef NETWORK_SEND_DOUBLE_SEED
880 _sync_seed_2 = p.Recv_uint32();
881#endif
882 }
883#endif
884 /* Receive the token. */
885 if (p.CanReadFromPacket(sizeof(uint8_t))) this->token = p.Recv_uint8();
886
887 /* Let the server know that we received this frame correctly
888 * We do this only once per day, to save some bandwidth ;) */
889 if (!_network_first_time && last_ack_frame < _frame_counter) {
890 last_ack_frame = _frame_counter + Ticks::DAY_TICKS;
891 Debug(net, 7, "Sent ACK at {}", _frame_counter);
892 SendAck();
893 }
894
895 return NETWORK_RECV_STATUS_OKAY;
896}
897
898 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SYNC(Packet &p)
899{
900 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
901
902 _sync_frame = p.Recv_uint32();
903 _sync_seed_1 = p.Recv_uint32();
904#ifdef NETWORK_SEND_DOUBLE_SEED
905 _sync_seed_2 = p.Recv_uint32();
906#endif
907
908 Debug(net, 9, "Client::Receive_SERVER_SYNC(): sync_frame={}, sync_seed_1={}", _sync_frame, _sync_seed_1);
909
910 return NETWORK_RECV_STATUS_OKAY;
911}
912
913 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMMAND(Packet &p)
914{
915 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
916
917 CommandPacket cp;
918 auto err = this->ReceiveCommand(p, cp);
919 cp.frame = p.Recv_uint32();
920 cp.my_cmd = p.Recv_bool();
921
922 Debug(net, 9, "Client::Receive_SERVER_COMMAND(): cmd={}, frame={}", cp.cmd, cp.frame);
923
924 if (err.has_value()) {
925 IConsolePrint(CC_WARNING, "Dropping server connection due to {}.", *err);
926 return NETWORK_RECV_STATUS_MALFORMED_PACKET;
927 }
928
929 this->incoming_queue.push_back(std::move(cp));
930
931 return NETWORK_RECV_STATUS_OKAY;
932}
933
934 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet &p)
935{
936 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
937
938 std::string name;
939 const NetworkClientInfo *ci = nullptr, *ci_to;
940
941 NetworkAction action = (NetworkAction)p.Recv_uint8();
942 ClientID client_id = (ClientID)p.Recv_uint32();
943 bool self_send = p.Recv_bool();
944 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
945 int64_t data = p.Recv_uint64();
946
947 Debug(net, 9, "Client::Receive_SERVER_CHAT(): action={}, client_id={}, self_send={}", action, client_id, self_send);
948
949 ci_to = NetworkClientInfo::GetByClientID(client_id);
950 if (ci_to == nullptr) return NETWORK_RECV_STATUS_OKAY;
951
952 /* Did we initiate the action locally? */
953 if (self_send) {
954 switch (action) {
955 case NETWORK_ACTION_CHAT_CLIENT:
956 /* For speaking to client we need the client-name */
957 name = ci_to->client_name;
958 ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
959 break;
960
961 /* For speaking to company, we need the company-name */
962 case NETWORK_ACTION_CHAT_COMPANY: {
963 StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
964
965 name = GetString(str, ci_to->client_playas);
966 ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
967 break;
968 }
969
970 default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
971 }
972 } else {
973 /* Display message from somebody else */
974 name = ci_to->client_name;
975 ci = ci_to;
976 }
977
978 if (ci != nullptr) {
979 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), self_send, name, msg, data);
980 }
981 return NETWORK_RECV_STATUS_OKAY;
982}
983
984 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_EXTERNAL_CHAT(Packet &p)
985{
986 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
987
988 std::string source = p.Recv_string(NETWORK_CHAT_LENGTH);
989 TextColour colour = (TextColour)p.Recv_uint16();
990 std::string user = p.Recv_string(NETWORK_CHAT_LENGTH);
991 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
992
993 Debug(net, 9, "Client::Receive_SERVER_EXTERNAL_CHAT(): source={}", source);
994
995 if (!IsValidConsoleColour(colour)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
996
997 NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, source);
998
999 return NETWORK_RECV_STATUS_OKAY;
1000}
1001
1002 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT(Packet &p)
1003{
1004 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1005
1006 ClientID client_id = (ClientID)p.Recv_uint32();
1007
1008 Debug(net, 9, "Client::Receive_SERVER_ERROR_QUIT(): client_id={}", client_id);
1009
1010 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1011 if (ci != nullptr) {
1012 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "", GetNetworkErrorMsg((NetworkErrorCode)p.Recv_uint8()));
1013 delete ci;
1014 }
1015
1016 InvalidateWindowData(WC_CLIENT_LIST, 0);
1017
1018 return NETWORK_RECV_STATUS_OKAY;
1019}
1020
1021 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_QUIT(Packet &p)
1022{
1023 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1024
1025 ClientID client_id = (ClientID)p.Recv_uint32();
1026
1027 Debug(net, 9, "Client::Receive_SERVER_QUIT(): client_id={}", client_id);
1028
1029 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1030 if (ci != nullptr) {
1031 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "", STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1032 delete ci;
1033 } else {
1034 Debug(net, 1, "Unknown client ({}) is leaving the game", client_id);
1035 }
1036
1037 InvalidateWindowData(WC_CLIENT_LIST, 0);
1038
1039 /* If we come here it means we could not locate the client.. strange :s */
1040 return NETWORK_RECV_STATUS_OKAY;
1041}
1042
1043 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_JOIN(Packet &p)
1044{
1045 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1046
1047 ClientID client_id = (ClientID)p.Recv_uint32();
1048
1049 Debug(net, 9, "Client::Receive_SERVER_JOIN(): client_id={}", client_id);
1050
1051 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1052 if (ci != nullptr) {
1053 NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name);
1054 }
1055
1056 InvalidateWindowData(WC_CLIENT_LIST, 0);
1057
1058 return NETWORK_RECV_STATUS_OKAY;
1059}
1060
1061 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet &)
1062{
1063 Debug(net, 9, "Client::Receive_SERVER_SHUTDOWN()");
1064
1065 /* Only when we're trying to join we really
1066 * care about the server shutting down. */
1067 if (this->status >= STATUS_JOIN) {
1068 ShowErrorMessage(GetEncodedString(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN), {}, WL_CRITICAL);
1069 }
1070
1071 if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
1072
1073 return NETWORK_RECV_STATUS_SERVER_ERROR;
1074}
1075
1076 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet &)
1077{
1078 Debug(net, 9, "Client::Receive_SERVER_NEWGAME()");
1079
1080 /* Only when we're trying to join we really
1081 * care about the server shutting down. */
1082 if (this->status >= STATUS_JOIN) {
1083 /* To throttle the reconnects a bit, every clients waits its
1084 * Client ID modulo 16 + 1 (value 0 means no reconnect).
1085 * This way reconnects should be spread out a bit. */
1086 _network_reconnect = _network_own_client_id % 16 + 1;
1087 ShowErrorMessage(GetEncodedString(STR_NETWORK_MESSAGE_SERVER_REBOOT), {}, WL_CRITICAL);
1088 }
1089
1090 if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
1091
1092 return NETWORK_RECV_STATUS_SERVER_ERROR;
1093}
1094
1095 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_RCON(Packet &p)
1096{
1097 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1098
1099 Debug(net, 9, "Client::Receive_SERVER_RCON()");
1100
1101 TextColour colour_code = (TextColour)p.Recv_uint16();
1102 if (!IsValidConsoleColour(colour_code)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1103
1104 std::string rcon_out = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
1105
1106 IConsolePrint(colour_code, rcon_out);
1107
1108 return NETWORK_RECV_STATUS_OKAY;
1109}
1110
1111 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MOVE(Packet &p)
1112{
1113 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1114
1115 /* Nothing more in this packet... */
1116 ClientID client_id = (ClientID)p.Recv_uint32();
1117 CompanyID company_id = (CompanyID)p.Recv_uint8();
1118
1119 Debug(net, 9, "Client::Receive_SERVER_MOVE(): client_id={}, company_id={}", client_id, company_id);
1120
1121 if (client_id == 0) {
1122 /* definitely an invalid client id, debug message and do nothing. */
1123 Debug(net, 1, "Received invalid client index = 0");
1124 return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1125 }
1126
1127 const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1128 /* Just make sure we do not try to use a client_index that does not exist */
1129 if (ci == nullptr) return NETWORK_RECV_STATUS_OKAY;
1130
1131 /* if not valid player, force spectator, else check player exists */
1132 if (!Company::IsValidID(company_id)) company_id = COMPANY_SPECTATOR;
1133
1134 if (client_id == _network_own_client_id) {
1135 SetLocalCompany(company_id);
1136 }
1137
1138 return NETWORK_RECV_STATUS_OKAY;
1139}
1140
1141 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(Packet &p)
1142{
1143 if (this->status < STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
1144
1145 _network_server_max_companies = p.Recv_uint8();
1146 _network_server_name = p.Recv_string(NETWORK_NAME_LENGTH);
1147
1148 InvalidateWindowData(WC_CLIENT_LIST, 0);
1149
1150 Debug(net, 9, "Client::Receive_SERVER_CONFIG_UPDATE(): max_companies={}", _network_server_max_companies);
1151
1152 return NETWORK_RECV_STATUS_OKAY;
1153}
1154
1158 void ClientNetworkGameSocketHandler::CheckConnection()
1159{
1160 /* Only once we're authorized we can expect a steady stream of packets. */
1161 if (this->status < STATUS_AUTHORIZED) return;
1162
1163 /* 5 seconds are roughly twice the server's "you're slow" threshold (1 game day). */
1164 std::chrono::steady_clock::duration lag = std::chrono::steady_clock::now() - this->last_packet;
1165 if (lag < std::chrono::seconds(5)) return;
1166
1167 /* 20 seconds are (way) more than 4 game days after which
1168 * the server will forcefully disconnect you. */
1169 if (lag > std::chrono::seconds(20)) {
1170 this->NetworkGameSocketHandler::CloseConnection();
1171 return;
1172 }
1173
1174 /* Prevent showing the lag message every tick; just update it when needed. */
1175 static std::chrono::steady_clock::duration last_lag = {};
1176 if (std::chrono::duration_cast<std::chrono::seconds>(last_lag) == std::chrono::duration_cast<std::chrono::seconds>(lag)) return;
1177
1178 last_lag = lag;
1179 ShowErrorMessage(
1180 GetEncodedString(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION),
1181 GetEncodedString(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, std::chrono::duration_cast<std::chrono::seconds>(lag).count()),
1182 WL_INFO);
1183}
1184
1185
1187 void NetworkClient_Connected()
1188{
1189 /* Set the frame-counter to 0 so nothing happens till we are ready */
1190 _frame_counter = 0;
1191 _frame_counter_server = 0;
1192 last_ack_frame = 0;
1193
1194 Debug(net, 9, "Client::NetworkClient_Connected()");
1195
1196 /* Request the game-info */
1197 MyClient::SendJoin();
1198}
1199
1205 void NetworkClientSendRcon(std::string_view password, std::string_view command)
1206{
1207 MyClient::SendRCon(password, command);
1208}
1209
1214 void NetworkClientRequestMove(CompanyID company_id)
1215{
1216 MyClient::SendMove(company_id);
1217}
1218
1223 void NetworkClientsToSpectators(CompanyID cid)
1224{
1225 Backup<CompanyID> cur_company(_current_company);
1226 /* If our company is changing owner, go to spectators */
1227 if (cid == _local_company) SetLocalCompany(COMPANY_SPECTATOR);
1228
1229 for (NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1230 if (ci->client_playas != cid) continue;
1231 NetworkTextMessage(NETWORK_ACTION_COMPANY_SPECTATOR, CC_DEFAULT, false, ci->client_name);
1232 ci->client_playas = COMPANY_SPECTATOR;
1233 }
1234
1235 cur_company.Restore();
1236}
1237
1245 bool NetworkIsValidClientName(std::string_view client_name)
1246{
1247 if (client_name.empty()) return false;
1248 if (client_name[0] == ' ') return false;
1249 return true;
1250}
1251
1267 bool NetworkValidateClientName(std::string &client_name)
1268{
1269 StrTrimInPlace(client_name);
1270 if (NetworkIsValidClientName(client_name)) return true;
1271
1272 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_BAD_PLAYER_NAME), {}, WL_ERROR);
1273 return false;
1274}
1275
1283 bool NetworkValidateOurClientName()
1284{
1285 return NetworkValidateClientName(_settings_client.network.client_name);
1286}
1287
1292 void NetworkUpdateClientName(const std::string &client_name)
1293{
1294 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
1295 if (ci == nullptr) return;
1296
1297 /* Don't change the name if it is the same as the old name */
1298 if (client_name == ci->client_name) return;
1299
1300 if (!_network_server) {
1301 MyClient::SendSetName(client_name);
1302 } else {
1303 /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */
1304 std::string temporary_name = client_name;
1305 if (NetworkMakeClientNameUnique(temporary_name)) {
1306 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name);
1307 ci->client_name = std::move(temporary_name);
1308 NetworkUpdateClientInfo(CLIENT_ID_SERVER);
1309 }
1310 }
1311}
1312
1321 void NetworkClientSendChat(NetworkAction action, DestType type, int dest, std::string_view msg, int64_t data)
1322{
1323 MyClient::SendChat(action, type, dest, msg, data);
1324}
1325
1331 bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio)
1332{
1333 /* Only companies actually playing can speak to team. Eg spectators cannot */
1334 if (!_settings_client.gui.prefer_teamchat || !Company::IsValidID(cio->client_playas)) return false;
1335
1336 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1337 if (ci->client_playas == cio->client_playas && ci != cio) return true;
1338 }
1339
1340 return false;
1341}
1342
1347uint NetworkMaxCompaniesAllowed()
1348{
1349 return _network_server ? _settings_client.network.max_companies : _network_server_max_companies;
1350}
1351
1356 bool NetworkMaxCompaniesReached()
1357{
1358 return Company::GetNumItems() >= NetworkMaxCompaniesAllowed();
1359}
ClientGamePasswordRequestHandler
Definition network_client.cpp:663
ClientGamePasswordRequestHandler::AskUserForPassword
virtual void AskUserForPassword(std::shared_ptr< NetworkAuthenticationPasswordRequest > request) override
Callback to trigger asking the user for the password.
Definition network_client.cpp:665
ClientGamePasswordRequestHandler::SendResponse
virtual void SendResponse() override
Callback to trigger sending the response for the password request.
Definition network_client.cpp:664
ClientNetworkGameSocketHandler
Class for handling the client side of the game connection.
Definition network_client.h:16
ClientNetworkGameSocketHandler::Receive_SERVER_QUIT
NetworkRecvStatus Receive_SERVER_QUIT(Packet &p) override
Notification that a client left the game: uint32_t ID of the client.
Definition network_client.cpp:1021
ClientNetworkGameSocketHandler::SendChat
static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, std::string_view msg, int64_t data)
Send a chat-packet over the network.
Definition network_client.cpp:394
ClientNetworkGameSocketHandler::my_client
static ClientNetworkGameSocketHandler * my_client
This is us!
Definition network_client.h:42
ClientNetworkGameSocketHandler::SendQuit
static NetworkRecvStatus SendQuit()
Tell the server we would like to quit.
Definition network_client.cpp:440
ClientNetworkGameSocketHandler::Receive_SERVER_SYNC
NetworkRecvStatus Receive_SERVER_SYNC(Packet &p) override
Sends a sync-check to the client: uint32_t Frame counter.
Definition network_client.cpp:898
ClientNetworkGameSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION
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...
Definition network_client.cpp:700
ClientNetworkGameSocketHandler::Receive_SERVER_MAP_SIZE
NetworkRecvStatus Receive_SERVER_MAP_SIZE(Packet &p) override
Sends the size of the map to the client.
Definition network_client.cpp:772
ClientNetworkGameSocketHandler::Receive
static bool Receive()
Check whether we received/can send some data from/to the server and when that's the case handle it ap...
Definition network_client.cpp:199
ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE
NetworkRecvStatus Receive_SERVER_MAP_DONE(Packet &p) override
Sends that all data of the map are sent to the client:
Definition network_client.cpp:799
ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO
NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p) override
Send information about a client: uint32_t ID of the client (always unique on a server.
Definition network_client.cpp:519
ClientNetworkGameSocketHandler::~ClientNetworkGameSocketHandler
~ClientNetworkGameSocketHandler()
Clear whatever we assigned.
Definition network_client.cpp:109
ClientNetworkGameSocketHandler::status
ServerStatus status
Status of the connection with the server.
Definition network_client.h:37
ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS
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...
Definition network_client.cpp:630
ClientNetworkGameSocketHandler::SendMove
static NetworkRecvStatus SendMove(CompanyID company)
Ask the server to move us.
Definition network_client.cpp:470
ClientNetworkGameSocketHandler::Receive_SERVER_WAIT
NetworkRecvStatus Receive_SERVER_WAIT(Packet &p) override
Notification that another client is currently receiving the map: uint8_t Number of clients waiting in...
Definition network_client.cpp:732
ClientNetworkGameSocketHandler::authentication_handler
std::unique_ptr< class NetworkAuthenticationClientHandler > authentication_handler
The handler for the authentication.
Definition network_client.h:18
ClientNetworkGameSocketHandler::savegame
std::shared_ptr< struct PacketReader > savegame
Packet reader for reading the savegame.
Definition network_client.h:20
ClientNetworkGameSocketHandler::IsConnected
static bool IsConnected()
Check whether the client is actually connected (and in the game).
Definition network_client.cpp:484
ClientNetworkGameSocketHandler::Receive_SERVER_EXTERNAL_CHAT
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...
Definition network_client.cpp:984
ClientNetworkGameSocketHandler::token
uint8_t token
The token we need to send back to the server to prove we're the right client.
Definition network_client.h:21
ClientNetworkGameSocketHandler::SendSetName
static NetworkRecvStatus SendSetName(const std::string &name)
Tell the server that we like to change the name of the client.
Definition network_client.cpp:426
ClientNetworkGameSocketHandler::NetworkExecuteLocalCommandQueue
friend void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
Definition network_command.cpp:244
ClientNetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT
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 ...
Definition network_client.cpp:1002
ClientNetworkGameSocketHandler::SendNewGRFsOk
static NetworkRecvStatus SendNewGRFsOk()
Tell the server we got all the NewGRFs.
Definition network_client.cpp:315
ClientNetworkGameSocketHandler::SendMapOk
static NetworkRecvStatus SendMapOk()
Tell the server we received the complete map.
Definition network_client.cpp:353
ClientNetworkGameSocketHandler::CheckConnection
void CheckConnection()
Check the connection's state, i.e.
Definition network_client.cpp:1158
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler
ClientNetworkGameSocketHandler(SOCKET s, std::string_view connection_string)
Create a new socket for the client side of the game connection.
Definition network_client.cpp:102
ClientNetworkGameSocketHandler::Receive_SERVER_RCON
NetworkRecvStatus Receive_SERVER_RCON(Packet &p) override
Send the result of an issues RCon command back to the client: uint16_t Colour code.
Definition network_client.cpp:1095
ClientNetworkGameSocketHandler::Receive_SERVER_BANNED
NetworkRecvStatus Receive_SERVER_BANNED(Packet &p) override
Notification that the client trying to join is banned.
Definition network_client.cpp:506
ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE
NetworkRecvStatus Receive_SERVER_CONFIG_UPDATE(Packet &p) override
Update the clients knowledge of the max settings: uint8_t Maximum number of companies allowed.
Definition network_client.cpp:1141
ClientNetworkGameSocketHandler::ClientError
void ClientError(NetworkRecvStatus res)
Handle an error coming from the client side.
Definition network_client.cpp:145
ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME
NetworkRecvStatus Receive_SERVER_WELCOME(Packet &p) override
The client is joined and ready to receive their map: uint32_t Own client ID.
Definition network_client.cpp:718
ClientNetworkGameSocketHandler::SendAck
static NetworkRecvStatus SendAck()
Send an acknowledgement from the server's ticks.
Definition network_client.cpp:366
ClientNetworkGameSocketHandler::Receive_SERVER_MAP_BEGIN
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.
Definition network_client.cpp:748
ClientNetworkGameSocketHandler::Receive_SERVER_JOIN
NetworkRecvStatus Receive_SERVER_JOIN(Packet &p) override
A client joined (PACKET_CLIENT_MAP_OK), what usually directly follows is a PACKET_SERVER_CLIENT_INFO:...
Definition network_client.cpp:1043
ClientNetworkGameSocketHandler::SendAuthResponse
static NetworkRecvStatus SendAuthResponse()
Set the game password as requested.
Definition network_client.cpp:328
ClientNetworkGameSocketHandler::GameLoop
static bool GameLoop()
Actual game loop for the client.
Definition network_client.cpp:224
ClientNetworkGameSocketHandler::Send
static void Send()
Send the packets of this socket handler.
Definition network_client.cpp:214
ClientNetworkGameSocketHandler::STATUS_JOIN
@ STATUS_JOIN
We are trying to join a server.
Definition network_client.h:26
ClientNetworkGameSocketHandler::STATUS_ENCRYPTED
@ STATUS_ENCRYPTED
The game authentication has completed and from here on the connection to the server is encrypted.
Definition network_client.h:28
ClientNetworkGameSocketHandler::STATUS_MAP
@ STATUS_MAP
The client is downloading the map.
Definition network_client.h:32
ClientNetworkGameSocketHandler::STATUS_AUTH_GAME
@ STATUS_AUTH_GAME
Last action was requesting game (server) password.
Definition network_client.h:27
ClientNetworkGameSocketHandler::STATUS_ACTIVE
@ STATUS_ACTIVE
The client is active within in the game.
Definition network_client.h:33
ClientNetworkGameSocketHandler::STATUS_MAP_WAIT
@ STATUS_MAP_WAIT
The client is waiting as someone else is downloading the map.
Definition network_client.h:31
ClientNetworkGameSocketHandler::STATUS_AUTHORIZED
@ STATUS_AUTHORIZED
The client is authorized at the server.
Definition network_client.h:30
ClientNetworkGameSocketHandler::SendRCon
static NetworkRecvStatus SendRCon(std::string_view password, std::string_view command)
Send a console command.
Definition network_client.cpp:455
ClientNetworkGameSocketHandler::Receive_SERVER_CHAT
NetworkRecvStatus Receive_SERVER_CHAT(Packet &p) override
Sends a chat-packet to the client: uint8_t ID of the action (see NetworkAction).
Definition network_client.cpp:934
ClientNetworkGameSocketHandler::Receive_SERVER_MOVE
NetworkRecvStatus Receive_SERVER_MOVE(Packet &p) override
Move a client from one company into another: uint32_t ID of the client.
Definition network_client.cpp:1111
ClientNetworkGameSocketHandler::SendCommand
static NetworkRecvStatus SendCommand(const CommandPacket &cp)
Send a command to the server.
Definition network_client.cpp:382
ClientNetworkGameSocketHandler::Receive_SERVER_FRAME
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...
Definition network_client.cpp:863
ClientNetworkGameSocketHandler::Receive_SERVER_COMMAND
NetworkRecvStatus Receive_SERVER_COMMAND(Packet &p) override
Sends a DoCommand to the client: uint8_t ID of the company (0..MAX_COMPANIES-1).
Definition network_client.cpp:913
ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME
NetworkRecvStatus Receive_SERVER_NEWGAME(Packet &p) override
Let the clients know that the server is loading a new map.
Definition network_client.cpp:1076
ClientNetworkGameSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
Definition network_client.cpp:117
ClientNetworkGameSocketHandler::SendGetMap
static NetworkRecvStatus SendGetMap()
Request the map from the server.
Definition network_client.cpp:340
ClientNetworkGameSocketHandler::Receive_SERVER_AUTH_REQUEST
NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p) override
Indication to the client that it needs to authenticate: uint8_t The NetworkAuthenticationMethod to us...
Definition network_client.cpp:675
ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DATA
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).
Definition network_client.cpp:785
ClientNetworkGameSocketHandler::Receive_SERVER_ERROR
NetworkRecvStatus Receive_SERVER_ERROR(Packet &p) override
The client made an error: uint8_t Error code caused (see NetworkErrorCode).
Definition network_client.cpp:580
ClientNetworkGameSocketHandler::SendError
static NetworkRecvStatus SendError(NetworkErrorCode errorno)
Send an error-packet over the network.
Definition network_client.cpp:411
ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN
NetworkRecvStatus Receive_SERVER_SHUTDOWN(Packet &p) override
Let the clients know that the server is closing.
Definition network_client.cpp:1061
ClientNetworkGameSocketHandler::SendJoin
static NetworkRecvStatus SendJoin()
Tell the server we would like to join.
Definition network_client.cpp:285
ClientNetworkGameSocketHandler::Receive_SERVER_FULL
NetworkRecvStatus Receive_SERVER_FULL(Packet &p) override
Notification that the server is full.
Definition network_client.cpp:496
NetworkAuthenticationClientHandler::RequestResult::AwaitUserInput
@ AwaitUserInput
We have requested some user input, but must wait on that.
NetworkAuthenticationClientHandler::RequestResult::Invalid
@ Invalid
We have received an invalid request.
NetworkAuthenticationClientHandler::RequestResult::ReadyForResponse
@ ReadyForResponse
We do not have to wait for user input, and can immediately respond to the server.
NetworkAuthenticationClientHandler::Create
static std::unique_ptr< NetworkAuthenticationClientHandler > Create(std::shared_ptr< NetworkAuthenticationPasswordRequestHandler > password_handler, std::string &secret_key, std::string &public_key)
Create a NetworkAuthenticationClientHandler.
Definition network_crypto.cpp:462
NetworkAuthenticationPasswordRequestHandler
Callback interface for client implementations to provide the handling of the password requests.
Definition network_crypto.h:84
NetworkGameSocketHandler
Base socket handler for all TCP sockets.
Definition tcp_game.h:140
NetworkGameSocketHandler::ReceivePackets
NetworkRecvStatus ReceivePackets()
Do the actual receiving of packets.
Definition tcp_game.cpp:131
NetworkGameSocketHandler::GetInfo
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition tcp_game.h:514
NetworkGameSocketHandler::ReceiveCommand
std::optional< std::string_view > ReceiveCommand(Packet &p, CommandPacket &cp)
Receives a command from the network.
Definition network_command.cpp:362
NetworkGameSocketHandler::client_id
ClientID client_id
Client identifier.
Definition tcp_game.h:485
NetworkGameSocketHandler::incoming_queue
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition tcp_game.h:488
NetworkGameSocketHandler::last_packet
std::chrono::steady_clock::time_point last_packet
Time we received the last frame.
Definition tcp_game.h:489
NetworkGameSocketHandler::SetInfo
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition tcp_game.h:504
NetworkGameSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(bool error=true) override
Functions to help ReceivePacket/SendPacket a bit A socket can make errors.
Definition tcp_game.cpp:40
NetworkSocketHandler::MarkClosed
void MarkClosed()
Mark the connection as closed.
Definition core.h:66
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:74
NetworkSocketHandler::send_encryption_handler
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition core.h:50
NetworkSocketHandler::receive_encryption_handler
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition core.h:49
NetworkTCPSocketHandler::sock
SOCKET sock
The socket currently connected to.
Definition tcp.h:38
NetworkTCPSocketHandler::SendPacket
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
NetworkTCPSocketHandler::SendPackets
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition tcp.cpp:76
NetworkTCPSocketHandler::CanSendReceive
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition tcp.cpp:194
SocialIntegration::EventEnterMultiplayer
static void EventEnterMultiplayer(uint map_width, uint map_height)
Event: user entered a multiplayer game.
Definition social_integration.cpp:234
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition timer_game_tick.h:75
TimerGameEconomy::date
static Date date
Current date in days (day counter).
Definition timer_game_economy.h:38
TimerGameEconomy::date_fract
static DateFract date_fract
Fractional part of the day.
Definition timer_game_economy.h:39
GetDrawStringCompanyColour
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
Definition company_cmd.cpp:153
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition company_cmd.cpp:55
SetLocalCompany
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...
Definition company_cmd.cpp:119
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
CCA_NEW
@ CCA_NEW
Create a new company.
Definition company_type.h:72
COMPANY_SPECTATOR
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
Definition company_type.h:21
COMPANY_NEW_COMPANY
static constexpr CompanyID COMPANY_NEW_COMPANY
The client wants a new company.
Definition company_type.h:20
CRR_NONE
@ CRR_NONE
Dummy reason for actions that don't need one.
Definition company_type.h:67
NETWORK_CHAT_LENGTH
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including '\0'.
Definition config.h:61
NETWORK_NAME_LENGTH
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including '\0'.
Definition config.h:53
NETWORK_PUBLIC_KEY_LENGTH
static const uint NETWORK_PUBLIC_KEY_LENGTH
The maximum length of the hexadecimal encoded public keys, in bytes including '\0'.
Definition config.h:101
NETWORK_RCONCOMMAND_LENGTH
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including '\0'.
Definition config.h:59
IConsolePrint
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:90
IsValidConsoleColour
bool IsValidConsoleColour(TextColour c)
Check whether the given TextColour is valid for console usage.
Definition console_gui.cpp:538
CC_WARNING
static const TextColour CC_WARNING
Colour for warning lines.
Definition console_type.h:25
CC_DEFAULT
static const TextColour CC_DEFAULT
Default colour of the console.
Definition console_type.h:23
NetworkRecvStatus
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition core.h:23
NETWORK_RECV_STATUS_DESYNC
@ NETWORK_RECV_STATUS_DESYNC
A desync did occur.
Definition core.h:25
NETWORK_RECV_STATUS_CLIENT_QUIT
@ 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
@ NETWORK_RECV_STATUS_SERVER_ERROR
The server told us we made an error.
Definition core.h:30
NETWORK_RECV_STATUS_SAVEGAME
@ NETWORK_RECV_STATUS_SAVEGAME
Something went wrong (down)loading the savegame.
Definition core.h:27
NETWORK_RECV_STATUS_CLOSE_QUERY
@ NETWORK_RECV_STATUS_CLOSE_QUERY
Done querying the server.
Definition core.h:33
NETWORK_RECV_STATUS_OKAY
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition core.h:24
NETWORK_RECV_STATUS_NEWGRF_MISMATCH
@ NETWORK_RECV_STATUS_NEWGRF_MISMATCH
We did not have the required NewGRFs.
Definition core.h:26
NETWORK_RECV_STATUS_SERVER_FULL
@ NETWORK_RECV_STATUS_SERVER_FULL
The server is full.
Definition core.h:31
NETWORK_RECV_STATUS_MALFORMED_PACKET
@ NETWORK_RECV_STATUS_MALFORMED_PACKET
We apparently send a malformed packet.
Definition core.h:29
NETWORK_RECV_STATUS_SERVER_BANNED
@ NETWORK_RECV_STATUS_SERVER_BANNED
The server has banned us.
Definition core.h:32
Debug
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
ClearErrorMessages
void ClearErrorMessages()
Clear all errors from the queue.
Definition error_gui.cpp:251
WL_ERROR
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition error.h:26
WL_CRITICAL
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition error.h:27
WL_INFO
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
ShowErrorMessage
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Definition error_gui.cpp:290
SaveLoadOperation
SaveLoadOperation
Operation performed on the file.
Definition fileio_type.h:52
SLO_LOAD
@ SLO_LOAD
File is being loaded.
Definition fileio_type.h:54
DetailedFileType
DetailedFileType
Kinds of files in each AbstractFileType.
Definition fileio_type.h:28
DFT_GAME_FILE
@ DFT_GAME_FILE
Save game or scenario file.
Definition fileio_type.h:31
Subdirectory
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition fileio_type.h:88
NO_DIRECTORY
@ NO_DIRECTORY
A path without any base directory.
Definition fileio_type.h:107
_game_session_stats
GameSessionStats _game_session_stats
Statistics about the current session.
Definition gfx.cpp:51
_switch_mode
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:49
TextColour
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
MILLISECONDS_PER_TICK
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition gfx_type.h:370
GetNetworkErrorMsg
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition network.cpp:310
_frame_counter_server
uint32_t _frame_counter_server
The frame_counter of the server, if in network-mode.
Definition network.cpp:77
_frame_counter
uint32_t _frame_counter
The current frame.
Definition network.cpp:79
_network_reconnect
uint8_t _network_reconnect
Reconnect timeout.
Definition network.cpp:73
_networking
bool _networking
are we in networking mode?
Definition network.cpp:66
_network_server
bool _network_server
network-server is active
Definition network.cpp:67
_sync_seed_1
uint32_t _sync_seed_1
Seed to compare during sync checks.
Definition network.cpp:82
_sync_frame
uint32_t _sync_frame
The frame to perform the sync check.
Definition network.cpp:86
_network_own_client_id
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:71
_network_first_time
bool _network_first_time
Whether we have finished joining or not.
Definition network.cpp:87
_frame_counter_max
uint32_t _frame_counter_max
To where we may go with our clients.
Definition network.cpp:78
network.h
Basic functions/variables used all over the place.
network_base.h
Base core network types and some helper functions to access them.
NetworkUpdateClientName
void NetworkUpdateClientName(const std::string &client_name)
Send the server our name as callback from the setting.
Definition network_client.cpp:1292
_network_join
NetworkJoinInfo _network_join
Information about the game to join to.
Definition network_client.cpp:278
NetworkValidateOurClientName
bool NetworkValidateOurClientName()
Convenience method for NetworkValidateClientName on _settings_client.network.client_name.
Definition network_client.cpp:1283
ClientNetworkEmergencySave
void ClientNetworkEmergencySave()
Create an emergency savegame when the network connection is lost.
Definition network_client.cpp:91
last_ack_frame
static uint32_t last_ack_frame
Last frame we performed an ack.
Definition network_client.cpp:270
NetworkMaxCompaniesReached
bool NetworkMaxCompaniesReached()
Check if max_companies has been reached on the server (local check only).
Definition network_client.cpp:1356
NetworkClientSendRcon
void NetworkClientSendRcon(std::string_view password, std::string_view command)
Send a remote console command.
Definition network_client.cpp:1205
NetworkMaxCompaniesAllowed
uint NetworkMaxCompaniesAllowed()
Get the maximum number of companies that are allowed by the server.
Definition network_client.cpp:1347
NetworkClientsToSpectators
void NetworkClientsToSpectators(CompanyID cid)
Move the clients of a company to the spectators.
Definition network_client.cpp:1223
_network_server_max_companies
static uint8_t _network_server_max_companies
Maximum number of companies of the currently joined server.
Definition network_client.cpp:273
NetworkClientPreferTeamChat
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio)
Tell whether the client has team members who they can chat to.
Definition network_client.cpp:1331
NetworkClientSendChat
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, std::string_view msg, int64_t data)
Send a chat message.
Definition network_client.cpp:1321
_network_server_name
std::string _network_server_name
The current name of the server you are on.
Definition network_client.cpp:275
NetworkClientRequestMove
void NetworkClientRequestMove(CompanyID company_id)
Notify the server of this client wanting to be moved to another company.
Definition network_client.cpp:1214
NetworkValidateClientName
bool NetworkValidateClientName(std::string &client_name)
Trim the given client name in place, i.e.
Definition network_client.cpp:1267
NetworkIsValidClientName
bool NetworkIsValidClientName(std::string_view client_name)
Check whether the given client name is deemed valid for use in network games.
Definition network_client.cpp:1245
network_client.h
Client part of the network protocol.
_network_join
NetworkJoinInfo _network_join
Information about the game to join to.
Definition network_client.cpp:278
NetworkClient_Connected
void NetworkClient_Connected()
Is called after a client is connected to the server.
Definition network_client.cpp:1187
NetworkUpdateClientInfo
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
Definition network_server.cpp:1529
network_gamelist.h
Handling of the list of games.
_network_join_status
NetworkJoinStatus _network_join_status
The status of joining.
Definition network_gui.cpp:1987
_network_join_waiting
uint8_t _network_join_waiting
The number of clients waiting in front of us.
Definition network_gui.cpp:1988
_network_join_bytes_total
uint32_t _network_join_bytes_total
The total number of bytes to download.
Definition network_gui.cpp:1990
_network_join_bytes
uint32_t _network_join_bytes
The number of bytes we already downloaded.
Definition network_gui.cpp:1989
network_gui.h
GUIs related to networking.
NetworkMakeClientNameUnique
bool NetworkMakeClientNameUnique(std::string &new_name)
Check whether a name is unique, and otherwise try to make it unique.
Definition network_server.cpp:1608
DestType
DestType
Destination of our chat messages.
Definition network_type.h:68
NetworkErrorCode
NetworkErrorCode
The error codes we send around in the protocols.
Definition network_type.h:99
NetworkAction
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition network_type.h:79
ClientID
ClientID
'Unique' identifier to be given to clients
Definition network_type.h:43
CLIENT_ID_SERVER
@ CLIENT_ID_SERVER
Servers always have this ID.
Definition network_type.h:45
FindGRFConfig
const GRFConfig * FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
Definition newgrf_config.cpp:596
FGCM_EXACT
@ FGCM_EXACT
Only find Grfs matching md5sum.
Definition newgrf_config.h:208
StateGameLoop
void StateGameLoop()
State controlling game loop.
Definition openttd.cpp:1210
GameMode
GameMode
Mode which defines the state of the game.
Definition openttd.h:18
SM_MENU
@ SM_MENU
Switch to game intro menu.
Definition openttd.h:33
_random
Randomizer _random
Random used in the game state calculations.
Definition random_func.cpp:36
DoAutoOrNetsave
void DoAutoOrNetsave(FiosNumberedSaveName &counter)
Create an autosave or netsave.
Definition saveload.cpp:3349
_file_to_saveload
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition saveload.cpp:78
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
lengthof
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
FormatArrayAsHex
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition string.cpp:77
StrTrimInPlace
void StrTrimInPlace(std::string &str)
Trim the spaces from given string in place, i.e.
Definition string.cpp:228
GetEncodedString
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
GetString
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
Backup
Class to backup a specific variable and restore it later.
Definition backup_type.hpp:21
Backup::Restore
void Restore()
Restore the variable.
Definition backup_type.hpp:110
ClientSettings::network
NetworkSettings network
settings related to the network
Definition settings_type.h:651
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition settings_type.h:650
CommandHelper
Definition command_func.h:83
CommandPacket
Everything we need to know about a command to be able to execute it.
Definition network_internal.h:95
CommandPacket::frame
uint32_t frame
the frame in which this packet is executed
Definition network_internal.h:97
CommandPacket::my_cmd
bool my_cmd
did the command originate from "me"
Definition network_internal.h:98
CommandPacket::cmd
Commands cmd
command being executed.
Definition network_internal.h:100
FileToSaveLoad::SetMode
void SetMode(const FiosType &ft, SaveLoadOperation fop=SLO_LOAD)
Set the mode and file type of the file to save or load.
Definition saveload.cpp:3421
FiosNumberedSaveName
A savegame name automatically numbered.
Definition fios.h:128
GRFConfig
Information about GRF, used in the game and (part of it) in savegames.
Definition newgrf_config.h:158
GRFIdentifier
Basic data to distinguish a GRF.
Definition newgrf_config.h:83
GRFIdentifier::grfid
uint32_t grfid
GRF ID (defined by Action 0x08)
Definition newgrf_config.h:84
GRFIdentifier::md5sum
MD5Hash md5sum
MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
Definition newgrf_config.h:85
GUISettings::prefer_teamchat
bool prefer_teamchat
choose the chat message target with <ENTER>, true=all clients, false=your team
Definition settings_type.h:183
GameSessionStats::start_time
std::chrono::steady_clock::time_point start_time
Time when the current game was started.
Definition openttd.h:56
GameSessionStats::savegame_size
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
LoadFilter
Interface for filtering a savegame till it is loaded.
Definition saveload_filter.h:14
Map::SizeX
static uint SizeX()
Get the size of the map along the X.
Definition map_func.h:272
Map::SizeY
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:281
NetworkClientInfo
Container for all information known about a client.
Definition network_base.h:24
NetworkClientInfo::GetByClientID
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition network.cpp:117
NetworkClientInfo::client_playas
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition network_base.h:28
NetworkClientInfo::client_name
std::string client_name
Name of the client.
Definition network_base.h:26
NetworkClientInfo::public_key
std::string public_key
The public key of the client.
Definition network_base.h:27
NetworkJoinInfo
Information required to join a server.
Definition network_client.h:109
NetworkJoinInfo::server_password
std::string server_password
The password of the server to join.
Definition network_client.h:113
NetworkJoinInfo::company
CompanyID company
The company to join.
Definition network_client.h:112
NetworkSettings::client_secret_key
std::string client_secret_key
The secret key of the client for authorized key logins.
Definition settings_type.h:358
NetworkSettings::max_companies
uint8_t max_companies
maximum amount of companies
Definition settings_type.h:364
NetworkSettings::client_name
std::string client_name
name of the player (as client)
Definition settings_type.h:357
NetworkSettings::client_public_key
std::string client_public_key
The public key of the client for authorized key logins.
Definition settings_type.h:359
PacketReader
Read some packets, and when do use that data as initial load filter.
Definition network_client.cpp:43
PacketReader::Read
size_t Read(uint8_t *rbuf, size_t size) override
Read a given number of bytes from the savegame.
Definition network_client.cpp:68
PacketReader::Buffer
std::deque< uint8_t > Buffer
The underlying buffer type that's being use.
Definition network_client.cpp:44
PacketReader::PacketReader
PacketReader()
Initialise everything.
Definition network_client.cpp:51
PacketReader::read_bytes
size_t read_bytes
The total number of read bytes.
Definition network_client.cpp:48
PacketReader::AddPacket
void AddPacket(Packet &p)
Add a packet to this buffer.
Definition network_client.cpp:59
PacketReader::iterator
Buffer::const_iterator iterator
Buffer we're going to write to/read from.
Definition network_client.cpp:47
PacketReader::Reset
void Reset() override
Reset this filter to read from the beginning of the file.
Definition network_client.cpp:80
PacketReader::buffer
Buffer buffer
Buffer with the raw save game data.
Definition network_client.cpp:46
Packet
Internal entity of a packet.
Definition packet.h:43
Packet::Recv_uint16
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition packet.cpp:332
Packet::Recv_uint64
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition packet.cpp:364
Packet::Recv_bool
bool Recv_bool()
Read a boolean from the packet.
Definition packet.cpp:309
Packet::Recv_uint32
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition packet.cpp:347
Packet::Recv_string
std::string Recv_string(size_t length, StringValidationSettings settings=StringValidationSetting::ReplaceWithQuestionMark)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition packet.cpp:425
Packet::Recv_uint8
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:318
Packet::CanReadFromPacket
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
Packet::TransferOut
ssize_t TransferOut(F transfer_function)
Transfer data from the packet to the given function.
Definition packet.h:128
PoolID< uint8_t, struct CompanyIDTag, 0xF, 0xFF >
Pool::PoolItem<&_networkclientinfo_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition pool_type.hpp:436
Pool::PoolItem<&_company_pool >::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition pool_type.hpp:417
Pool::PoolItem<&_networkclientinfo_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition pool_type.hpp:357
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
Randomizer::state
uint32_t state[2]
The state of the randomizer.
Definition random_func.hpp:29
PACKET_CLIENT_IDENTIFY
@ PACKET_CLIENT_IDENTIFY
Client telling the server the client's name and requested company.
Definition tcp_game.h:67
PACKET_CLIENT_GETMAP
@ PACKET_CLIENT_GETMAP
Client requests the actual map.
Definition tcp_game.h:78
PACKET_CLIENT_ERROR
@ PACKET_CLIENT_ERROR
A client reports an error to the server.
Definition tcp_game.h:123
PACKET_CLIENT_JOIN
@ PACKET_CLIENT_JOIN
The client telling the server it wants to join.
Definition tcp_game.h:36
PACKET_CLIENT_AUTH_RESPONSE
@ PACKET_CLIENT_AUTH_RESPONSE
The client responds to the authentication request.
Definition tcp_game.h:63
PACKET_CLIENT_NEWGRFS_CHECKED
@ PACKET_CLIENT_NEWGRFS_CHECKED
Client acknowledges that it has all required NewGRFs.
Definition tcp_game.h:71
PACKET_CLIENT_COMMAND
@ PACKET_CLIENT_COMMAND
Client executed a command and sends it to the server.
Definition tcp_game.h:100
PACKET_CLIENT_SET_NAME
@ PACKET_CLIENT_SET_NAME
A client changes its name.
Definition tcp_game.h:117
PACKET_CLIENT_ACK
@ PACKET_CLIENT_ACK
The client tells the server which frame it has executed.
Definition tcp_game.h:96
PACKET_CLIENT_RCON
@ PACKET_CLIENT_RCON
Client asks the server to execute some command.
Definition tcp_game.h:109
PACKET_CLIENT_MAP_OK
@ PACKET_CLIENT_MAP_OK
Client tells the server that it received the whole map.
Definition tcp_game.h:84
PACKET_CLIENT_QUIT
@ PACKET_CLIENT_QUIT
A client tells the server it is going to quit.
Definition tcp_game.h:121
PACKET_CLIENT_MOVE
@ PACKET_CLIENT_MOVE
A client would like to be moved to another company.
Definition tcp_game.h:113
PACKET_CLIENT_CHAT
@ PACKET_CLIENT_CHAT
Client said something that should be distributed.
Definition tcp_game.h:104
CSleep
void CSleep(int milliseconds)
Sleep on the current thread for a defined time.
Definition thread.h:24
CloseWindowById
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:1193
InvalidateWindowData
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:3294
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3176
WN_NETWORK_STATUS_WINDOW_JOIN
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition window_type.h:44
WC_CLIENT_LIST
@ WC_CLIENT_LIST
Client list; Window numbers:
Definition window_type.h:489
WC_NETWORK_STATUS_WINDOW
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers:
Definition window_type.h:496