OpenTTD Source 20250312-master-gcdcc6b491d
network.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
12#include "../strings_func.h"
13#include "../command_func.h"
14#include "../timer/timer_game_tick.h"
15#include "../timer/timer_game_economy.h"
16#include "network_admin.h"
17#include "network_client.h"
18#include "network_query.h"
19#include "network_server.h"
20#include "network_content.h"
21#include "network_udp.h"
22#include "network_gamelist.h"
23#include "network_base.h"
24#include "network_coordinator.h"
25#include "core/udp.h"
26#include "core/host.h"
27#include "network_gui.h"
28#include "../console_func.h"
29#include "../3rdparty/md5/md5.h"
30#include "../core/random_func.hpp"
31#include "../window_func.h"
32#include "../company_func.h"
33#include "../company_base.h"
34#include "../landscape_type.h"
35#include "../rev.h"
36#include "../core/pool_func.hpp"
37#include "../gfx_func.h"
38#include "../error.h"
39#include "../misc_cmd.h"
40#ifdef DEBUG_DUMP_COMMANDS
41# include "../fileio_func.h"
42#endif
43#include <charconv>
44#include <sstream>
45#include <iomanip>
46
47#include "../safeguards.h"
48
49#ifdef DEBUG_DUMP_COMMANDS
55bool _ddc_fastforward = true;
56#endif /* DEBUG_DUMP_COMMANDS */
57
60
64
81uint32_t _sync_seed_1;
82#ifdef NETWORK_SEND_DOUBLE_SEED
83uint32_t _sync_seed_2;
84#endif
85uint32_t _sync_frame;
87
90
91extern std::string GenerateUid(std::string_view subject);
92
98{
99 return !NetworkClientSocket::Iterate().empty();
100}
101
106{
107 /* Delete the chat window, if you were chatting with this client. */
109}
110
117{
119 if (ci->client_id == client_id) return ci;
120 }
121
122 return nullptr;
123}
124
131{
132 Company *c = Company::GetIfValid(company_id);
133 return c != nullptr && c->allow_list.Contains(this->public_key);
134}
135
142{
144 return info != nullptr && info->CanJoinCompany(company_id);
145}
146
153{
155 if (cs->client_id == client_id) return cs;
156 }
157
158 return nullptr;
159}
160
161
168static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
169{
170 return std::ranges::find_if(*authorized_keys, [authorized_key](auto &value) { return StrEqualsIgnoreCase(value, authorized_key); });
171}
172
178bool NetworkAuthorizedKeys::Contains(std::string_view key) const
179{
180 return FindKey(this, key) != this->end();
181}
182
188bool NetworkAuthorizedKeys::Add(std::string_view key)
189{
190 if (key.empty()) return false;
191
192 auto iter = FindKey(this, key);
193 if (iter != this->end()) return false;
194
195 this->emplace_back(key);
196 return true;
197}
198
204bool NetworkAuthorizedKeys::Remove(std::string_view key)
205{
206 auto iter = FindKey(this, key);
207 if (iter == this->end()) return false;
208
209 this->erase(iter);
210 return true;
211}
212
213
214uint8_t NetworkSpectatorCount()
215{
216 uint8_t count = 0;
217
218 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
219 if (ci->client_playas == COMPANY_SPECTATOR) count++;
220 }
221
222 /* Don't count a dedicated server as spectator */
223 if (_network_dedicated) count--;
224
225 return count;
226}
227
228
229/* This puts a text-message to the console, or in the future, the chat-box,
230 * (to keep it all a bit more general)
231 * If 'self_send' is true, this is the client who is sending the message */
232void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str, StringParameter &&data)
233{
234 std::string string;
235 switch (action) {
236 case NETWORK_ACTION_SERVER_MESSAGE:
237 /* Ignore invalid messages */
238 string = GetString(STR_NETWORK_SERVER_MESSAGE, str);
239 colour = CC_DEFAULT;
240 break;
241 case NETWORK_ACTION_COMPANY_SPECTATOR:
242 colour = CC_DEFAULT;
243 string = GetString(STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE, name);
244 break;
245 case NETWORK_ACTION_COMPANY_JOIN:
246 colour = CC_DEFAULT;
247 string = GetString(STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN, name, str);
248 break;
249 case NETWORK_ACTION_COMPANY_NEW:
250 colour = CC_DEFAULT;
251 string = GetString(STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW, name, std::move(data));
252 break;
253 case NETWORK_ACTION_JOIN:
254 /* Show the Client ID for the server but not for the client. */
255 string = _network_server ?
256 GetString(STR_NETWORK_MESSAGE_CLIENT_JOINED_ID, name, std::move(data)) :
257 GetString(STR_NETWORK_MESSAGE_CLIENT_JOINED, name);
258 break;
259 case NETWORK_ACTION_LEAVE: string = GetString(STR_NETWORK_MESSAGE_CLIENT_LEFT, name, std::move(data)); break;
260 case NETWORK_ACTION_NAME_CHANGE: string = GetString(STR_NETWORK_MESSAGE_NAME_CHANGE, name, str); break;
261 case NETWORK_ACTION_GIVE_MONEY: string = GetString(STR_NETWORK_MESSAGE_GIVE_MONEY, name, std::move(data), str); break;
262 case NETWORK_ACTION_KICKED: string = GetString(STR_NETWORK_MESSAGE_KICKED, name, str); break;
263 case NETWORK_ACTION_CHAT_COMPANY: string = GetString(self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY, name, str); break;
264 case NETWORK_ACTION_CHAT_CLIENT: string = GetString(self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT, name, str); break;
265 case NETWORK_ACTION_EXTERNAL_CHAT: string = GetString(STR_NETWORK_CHAT_EXTERNAL, std::move(data), name, str); break;
266 default: string = GetString(STR_NETWORK_CHAT_ALL, name, str); break;
267 }
268
269 /* All of these strings start with "***". These characters are interpreted as both left-to-right and
270 * right-to-left characters depending on the context. As the next text might be an user's name, the
271 * user name's characters will influence the direction of the "***" instead of the language setting
272 * of the game. Manually set the direction of the "***" by inserting a text-direction marker. */
273 std::ostringstream stream;
274 std::ostreambuf_iterator<char> iterator(stream);
276 std::string message = stream.str() + string;
277
278 Debug(desync, 1, "msg: {:08x}; {:02x}; {}", TimerGameEconomy::date, TimerGameEconomy::date_fract, message);
279 IConsolePrint(colour, message);
281}
282
283/* Calculate the frame-lag of a client */
284uint NetworkCalculateLag(const NetworkClientSocket *cs)
285{
286 int lag = cs->last_frame_server - cs->last_frame;
287 /* This client has missed their ACK packet after 1 DAY_TICKS..
288 * so we increase their lag for every frame that passes!
289 * The packet can be out by a max of _net_frame_freq */
290 if (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq < _frame_counter) {
291 lag += _frame_counter - (cs->last_frame_server + Ticks::DAY_TICKS + _settings_client.network.frame_freq);
292 }
293 return lag;
294}
295
296
297/* There was a non-recoverable error, drop back to the main menu with a nice
298 * error */
299void ShowNetworkError(StringID error_string)
300{
303}
304
311{
312 /* List of possible network errors, used by
313 * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
314 static const StringID network_error_strings[] = {
315 STR_NETWORK_ERROR_CLIENT_GENERAL,
316 STR_NETWORK_ERROR_CLIENT_DESYNC,
317 STR_NETWORK_ERROR_CLIENT_SAVEGAME,
318 STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST,
319 STR_NETWORK_ERROR_CLIENT_PROTOCOL_ERROR,
320 STR_NETWORK_ERROR_CLIENT_NEWGRF_MISMATCH,
321 STR_NETWORK_ERROR_CLIENT_NOT_AUTHORIZED,
322 STR_NETWORK_ERROR_CLIENT_NOT_EXPECTED,
323 STR_NETWORK_ERROR_CLIENT_WRONG_REVISION,
324 STR_NETWORK_ERROR_CLIENT_NAME_IN_USE,
325 STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD,
326 STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH,
327 STR_NETWORK_ERROR_CLIENT_KICKED,
328 STR_NETWORK_ERROR_CLIENT_CHEATER,
329 STR_NETWORK_ERROR_CLIENT_SERVER_FULL,
330 STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS,
331 STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD,
332 STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER,
333 STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
334 STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
335 STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
336 STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST,
337 STR_NETWORK_ERROR_CLIENT_NO_AUTHENTICATION_METHOD_AVAILABLE,
338 };
339 static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
340
341 if (err >= (ptrdiff_t)lengthof(network_error_strings)) err = NETWORK_ERROR_GENERAL;
342
343 return network_error_strings[err];
344}
345
351void NetworkHandlePauseChange(PauseModes prev_mode, PauseMode changed_mode)
352{
353 if (!_networking) return;
354
355 switch (changed_mode) {
357 case PauseMode::Join:
361 bool changed = _pause_mode.None() != prev_mode.None();
362 bool paused = _pause_mode.Any();
363 if (!paused && !changed) return;
364
365 std::string str;
366 if (!changed) {
367 std::array<StringParameter, 5> params{};
368 auto it = params.begin();
369 if (_pause_mode.Test(PauseMode::Normal)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL;
370 if (_pause_mode.Test(PauseMode::Join)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS;
371 if (_pause_mode.Test(PauseMode::GameScript)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT;
372 if (_pause_mode.Test(PauseMode::ActiveClients)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS;
373 if (_pause_mode.Test(PauseMode::LinkGraph)) *it++ = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH;
374 str = GetStringWithArgs(STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 + std::distance(params.begin(), it) - 1, {params.begin(), it});
375 } else {
376 StringID reason;
377 switch (changed_mode) {
378 case PauseMode::Normal: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL; break;
379 case PauseMode::Join: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS; break;
380 case PauseMode::GameScript: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT; break;
381 case PauseMode::ActiveClients: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS; break;
382 case PauseMode::LinkGraph: reason = STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH; break;
383 default: NOT_REACHED();
384 }
385 str = GetString(paused ? STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED : STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED, reason);
386 }
387
388 NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, "", str);
389 break;
390 }
391
392 default:
393 return;
394 }
395}
396
397
406static void CheckPauseHelper(bool pause, PauseMode pm)
407{
408 if (pause == _pause_mode.Test(pm)) return;
409
410 Command<CMD_PAUSE>::Post(pm, pause);
411}
412
419{
420 uint count = 0;
421
422 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
423 if (cs->status != NetworkClientSocket::STATUS_ACTIVE) continue;
424 if (!Company::IsValidID(cs->GetInfo()->client_playas)) continue;
425 count++;
426 }
427
428 return count;
429}
430
443
449{
450 for (const NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
451 if (cs->status >= NetworkClientSocket::STATUS_AUTHORIZED && cs->status < NetworkClientSocket::STATUS_ACTIVE) return true;
452 }
453
454 return false;
455}
456
468
475std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id)
476{
477 std::string_view ip = connection_string;
478 if (company_id == nullptr) return ip;
479
480 size_t offset = ip.find_last_of('#');
481 if (offset != std::string::npos) {
482 std::string_view company_string = ip.substr(offset + 1);
483 ip = ip.substr(0, offset);
484
485 uint8_t company_value;
486 auto [_, err] = std::from_chars(company_string.data(), company_string.data() + company_string.size(), company_value);
487 if (err == std::errc()) {
488 if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) {
489 if (company_value > MAX_COMPANIES || company_value == 0) {
490 *company_id = COMPANY_SPECTATOR;
491 } else {
492 /* "#1" means the first company, which has index 0. */
493 *company_id = (CompanyID)(company_value - 1);
494 }
495 } else {
496 *company_id = (CompanyID)company_value;
497 }
498 }
499 }
500
501 return ip;
502}
503
519std::string_view ParseFullConnectionString(const std::string &connection_string, uint16_t &port, CompanyID *company_id)
520{
521 std::string_view ip = ParseCompanyFromConnectionString(connection_string, company_id);
522
523 size_t port_offset = ip.find_last_of(':');
524 size_t ipv6_close = ip.find_last_of(']');
525 if (port_offset != std::string::npos && (ipv6_close == std::string::npos || ipv6_close < port_offset)) {
526 std::string_view port_string = ip.substr(port_offset + 1);
527 ip = ip.substr(0, port_offset);
528 std::from_chars(port_string.data(), port_string.data() + port_string.size(), port);
529 }
530 return ip;
531}
532
539std::string NormalizeConnectionString(const std::string &connection_string, uint16_t default_port)
540{
541 uint16_t port = default_port;
542 std::string_view ip = ParseFullConnectionString(connection_string, port);
543 return std::string(ip) + ":" + std::to_string(port);
544}
545
554NetworkAddress ParseConnectionString(const std::string &connection_string, uint16_t default_port)
555{
556 uint16_t port = default_port;
557 std::string_view ip = ParseFullConnectionString(connection_string, port);
558 return NetworkAddress(ip, port);
559}
560
566/* static */ void ServerNetworkGameSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
567{
568 /* Register the login */
570
572 cs->client_address = address; // Save the IP of the client
573
575}
576
581static void InitializeNetworkPools(bool close_admins = true)
582{
584 if (close_admins) to_clean.Set(PoolType::NetworkAdmin);
585 PoolBase::Clean(to_clean);
586}
587
592void NetworkClose(bool close_admins)
593{
594 if (_network_server) {
595 if (close_admins) {
597 as->CloseConnection(true);
598 }
599 }
600
601 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
602 cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
603 }
606
608 } else {
609 if (MyClient::my_client != nullptr) {
612 }
613
615 }
616 NetworkGameSocketHandler::ProcessDeferredDeletions();
617
619
620 _networking = false;
621 _network_server = false;
622
624
625 InitializeNetworkPools(close_admins);
626}
627
628/* Initializes the network (cleans sockets and stuff) */
629static void NetworkInitialize(bool close_admins = true)
630{
631 InitializeNetworkPools(close_admins);
632
633 _sync_frame = 0;
634 _network_first_time = true;
635
637}
638
641private:
642 std::string connection_string;
643
644public:
645 TCPQueryConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
646
647 void OnFailure() override
648 {
649 Debug(net, 9, "Query::OnFailure(): connection_string={}", this->connection_string);
650
651 NetworkGameList *item = NetworkGameListAddItem(connection_string);
652 item->status = NGLS_OFFLINE;
653 item->refreshing = false;
654
656 }
657
658 void OnConnect(SOCKET s) override
659 {
660 Debug(net, 9, "Query::OnConnect(): connection_string={}", this->connection_string);
661
662 QueryNetworkGameSocketHandler::QueryServer(s, this->connection_string);
663 }
664};
665
670void NetworkQueryServer(const std::string &connection_string)
671{
672 if (!_network_available) return;
673
674 Debug(net, 9, "NetworkQueryServer(): connection_string={}", connection_string);
675
676 /* Mark the entry as refreshing, so the GUI can show the refresh is pending. */
677 NetworkGameList *item = NetworkGameListAddItem(connection_string);
678 item->refreshing = true;
679
680 TCPConnecter::Create<TCPQueryConnecter>(connection_string);
681}
682
692NetworkGameList *NetworkAddServer(const std::string &connection_string, bool manually, bool never_expire)
693{
694 if (connection_string.empty()) return nullptr;
695
696 /* Ensure the item already exists in the list */
697 NetworkGameList *item = NetworkGameListAddItem(connection_string);
698 if (item->info.server_name.empty()) {
700 item->info.server_name = connection_string;
701
703
704 NetworkQueryServer(connection_string);
705 }
706
707 if (manually) item->manually = true;
708 if (never_expire) item->version = INT32_MAX;
709
710 return item;
711}
712
718void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
719{
720 for (const auto &iter : _network_bind_list) {
721 addresses->emplace_back(iter.c_str(), port);
722 }
723
724 /* No address, so bind to everything. */
725 if (addresses->empty()) {
726 addresses->emplace_back("", port);
727 }
728}
729
730/* Generates the list of manually added hosts from NetworkGameList and
731 * dumps them into the array _network_host_list. This array is needed
732 * by the function that generates the config file. */
733void NetworkRebuildHostList()
734{
735 _network_host_list.clear();
736
737 for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) {
738 if (item->manually) _network_host_list.emplace_back(item->connection_string);
739 }
740}
741
744private:
745 std::string connection_string;
746
747public:
748 TCPClientConnecter(const std::string &connection_string) : TCPServerConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
749
750 void OnFailure() override
751 {
752 Debug(net, 9, "Client::OnFailure(): connection_string={}", this->connection_string);
753
754 ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
755 }
756
757 void OnConnect(SOCKET s) override
758 {
759 Debug(net, 9, "Client::OnConnect(): connection_string={}", this->connection_string);
760
761 _networking = true;
763 new ClientNetworkGameSocketHandler(s, this->connection_string);
764 IConsoleCmdExec("exec scripts/on_client.scr 0");
766 }
767};
768
785bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password)
786{
787 Debug(net, 9, "NetworkClientConnectGame(): connection_string={}", connection_string);
788
789 CompanyID join_as = default_company;
790 std::string resolved_connection_string = ServerAddress::Parse(connection_string, NETWORK_DEFAULT_PORT, &join_as).connection_string;
791
792 if (!_network_available) return false;
793 if (!NetworkValidateOurClientName()) return false;
794
795 _network_join.connection_string = resolved_connection_string;
796 _network_join.company = join_as;
797 _network_join.server_password = join_server_password;
798
799 if (_game_mode == GM_MENU) {
800 /* From the menu we can immediately continue with the actual join. */
802 } else {
803 /* When already playing a game, first go back to the main menu. This
804 * disconnects the user from the current game, meaning we can safely
805 * load in the new. After all, there is little point in continuing to
806 * play on a server if we are connecting to another one.
807 */
809 }
810 return true;
811}
812
819{
821 NetworkInitialize();
822
824 Debug(net, 9, "status = CONNECTING");
825 _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
826 ShowJoinStatusWindow();
827
828 TCPConnecter::Create<TCPClientConnecter>(_network_join.connection_string);
829}
830
831static void NetworkInitGameInfo()
832{
833 FillStaticNetworkServerGameInfo();
834 /* The server is a client too */
835 _network_game_info.clients_on = _network_dedicated ? 0 : 1;
836
837 /* There should be always space for the server. */
841
843
846}
847
858bool NetworkValidateServerName(std::string &server_name)
859{
860 StrTrimInPlace(server_name);
861 if (!server_name.empty()) return true;
862
863 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_BAD_SERVER_NAME), {}, WL_ERROR);
864 return false;
865}
866
874{
875 static const std::string fallback_client_name = "Unnamed Client";
877 if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) {
878 Debug(net, 1, "No \"client_name\" has been set, using \"{}\" instead. Please set this now using the \"name <new name>\" command", fallback_client_name);
879 _settings_client.network.client_name = fallback_client_name;
880 }
881
882 static const std::string fallback_server_name = "Unnamed Server";
884 if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) {
885 Debug(net, 1, "No \"server_name\" has been set, using \"{}\" instead. Please set this now using the \"server_name <new name>\" command", fallback_server_name);
886 _settings_client.network.server_name = fallback_server_name;
887 }
888}
889
890bool NetworkServerStart()
891{
892 if (!_network_available) return false;
893
894 /* Call the pre-scripts */
895 IConsoleCmdExec("exec scripts/pre_server.scr 0");
896 if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
897
898 /* Check for the client and server names to be set, but only after the scripts had a chance to set them.*/
900
901 NetworkDisconnect(false);
902 NetworkInitialize(false);
904 Debug(net, 5, "Starting listeners for clients");
906
907 /* Only listen for admins when the authentication is configured. */
908 if (_settings_client.network.AdminAuthenticationConfigured()) {
909 Debug(net, 5, "Starting listeners for admins");
911 }
912
913 /* Try to start UDP-server */
914 Debug(net, 5, "Starting listeners for incoming server queries");
916
917 _network_server = true;
918 _networking = true;
919 _frame_counter = 0;
924
926
927 NetworkInitGameInfo();
928
929 if (_settings_client.network.server_game_type != SERVER_GAME_TYPE_LOCAL) {
931 }
932
933 /* execute server initialization script */
934 IConsoleCmdExec("exec scripts/on_server.scr 0");
935 /* if the server is dedicated ... add some other script */
936 if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
937
938 return true;
939}
940
946{
947 if (!_network_server) return;
948
949 /* Update the static game info to set the values from the new game. */
951
953
954 if (!_network_dedicated) {
957 if (c != nullptr && ci != nullptr) {
958 ci->client_playas = c->index;
959
960 /*
961 * If the company has not been named yet, the company was just started.
962 * Otherwise it would have gotten a name already, so announce it as a new company.
963 */
964 if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) NetworkServerNewCompany(c, ci);
965 }
966
967 ShowClientList();
968 } else {
969 /* welcome possibly still connected admins - this can only happen on a dedicated server. */
971 }
972}
973
974/* The server is rebooting...
975 * The only difference with NetworkDisconnect, is the packets that is sent */
976void NetworkReboot()
977{
978 if (_network_server) {
979 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
980 cs->SendNewGame();
981 cs->SendPackets();
982 }
983
985 as->SendNewGame();
986 as->SendPackets();
987 }
988 }
989
990 /* For non-dedicated servers we have to kick the admins as we are not
991 * certain that we will end up in a new network game. */
993}
994
999void NetworkDisconnect(bool close_admins)
1000{
1001 if (_network_server) {
1002 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
1003 cs->SendShutdown();
1004 cs->SendPackets();
1005 }
1006
1007 if (close_admins) {
1009 as->SendShutdown();
1010 as->SendPackets();
1011 }
1012 }
1013 }
1014
1016
1017 NetworkClose(close_admins);
1018
1019 /* Reinitialize the UDP stack, i.e. close all existing connections. */
1021}
1022
1028{
1029 if (!_networking) return;
1030
1032 case SERVER_GAME_TYPE_LOCAL:
1034 break;
1035
1036 case SERVER_GAME_TYPE_INVITE_ONLY:
1037 case SERVER_GAME_TYPE_PUBLIC:
1039 break;
1040
1041 default:
1042 NOT_REACHED();
1043 }
1044}
1045
1050static bool NetworkReceive()
1051{
1052 bool result;
1053 if (_network_server) {
1056 } else {
1058 }
1059 NetworkGameSocketHandler::ProcessDeferredDeletions();
1060 return result;
1061}
1062
1063/* This sends all buffered commands (if possible) */
1064static void NetworkSend()
1065{
1066 if (_network_server) {
1069 } else {
1071 }
1072 NetworkGameSocketHandler::ProcessDeferredDeletions();
1073}
1074
1091
1092/* The main loop called from ttd.c
1093 * Here we also have to do StateGameLoop if needed! */
1094void NetworkGameLoop()
1095{
1096 if (!_networking) return;
1097
1098 if (!NetworkReceive()) return;
1099
1100 if (_network_server) {
1101 /* Log the sync state to check for in-syncedness of replays. */
1103 /* We don't want to log multiple times if paused. */
1104 static TimerGameEconomy::Date last_log;
1105 if (last_log != TimerGameEconomy::date) {
1106 Debug(desync, 1, "sync: {:08x}; {:02x}; {:08x}; {:08x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _random.state[0], _random.state[1]);
1107 last_log = TimerGameEconomy::date;
1108 }
1109 }
1110
1111#ifdef DEBUG_DUMP_COMMANDS
1112 /* Loading of the debug commands from -ddesync>=1 */
1113 static auto f = FioFOpenFile("commands.log", "rb", SAVE_DIR);
1114 static TimerGameEconomy::Date next_date(0);
1115 static uint32_t next_date_fract;
1116 static CommandPacket *cp = nullptr;
1117 static bool check_sync_state = false;
1118 static uint32_t sync_state[2];
1119 if (!f.has_value() && next_date == 0) {
1120 Debug(desync, 0, "Cannot open commands.log");
1121 next_date = TimerGameEconomy::Date(1);
1122 }
1123
1124 while (f.has_value() && !feof(*f)) {
1125 if (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract == next_date_fract) {
1126 if (cp != nullptr) {
1127 NetworkSendCommand(cp->cmd, cp->err_msg, nullptr, cp->company, cp->data);
1128 Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {} ({})", TimerGameEconomy::date, TimerGameEconomy::date_fract, (int)_current_company, cp->cmd, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd));
1129 delete cp;
1130 cp = nullptr;
1131 }
1132 if (check_sync_state) {
1133 if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) {
1134 Debug(desync, 0, "Sync check: {:08x}; {:02x}; match", TimerGameEconomy::date, TimerGameEconomy::date_fract);
1135 } else {
1136 Debug(desync, 0, "Sync check: {:08x}; {:02x}; mismatch expected {{{:08x}, {:08x}}}, got {{{:08x}, {:08x}}}",
1137 TimerGameEconomy::date, TimerGameEconomy::date_fract, sync_state[0], sync_state[1], _random.state[0], _random.state[1]);
1138 NOT_REACHED();
1139 }
1140 check_sync_state = false;
1141 }
1142 }
1143
1144 /* Skip all entries in the command-log till we caught up with the current game again. */
1145 if (TimerGameEconomy::date > next_date || (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract > next_date_fract)) {
1146 Debug(desync, 0, "Skipping to next command at {:08x}:{:02x}", next_date, next_date_fract);
1147 if (cp != nullptr) {
1148 delete cp;
1149 cp = nullptr;
1150 }
1151 check_sync_state = false;
1152 }
1153
1154 if (cp != nullptr || check_sync_state) break;
1155
1156 char buff[4096];
1157 if (fgets(buff, lengthof(buff), *f) == nullptr) break;
1158
1159 char *p = buff;
1160 /* Ignore the "[date time] " part of the message */
1161 if (*p == '[') {
1162 p = strchr(p, ']');
1163 if (p == nullptr) break;
1164 p += 2;
1165 }
1166
1167 if (strncmp(p, "cmd: ", 5) == 0
1168#ifdef DEBUG_FAILED_DUMP_COMMANDS
1169 || strncmp(p, "cmdf: ", 6) == 0
1170#endif
1171 ) {
1172 p += 5;
1173 if (*p == ' ') p++;
1174 cp = new CommandPacket();
1175 int company;
1176 uint cmd;
1177 char buffer[256];
1178 uint32_t next_date_raw;
1179 int ret = sscanf(p, "%x; %x; %x; %x; %x; %255s", &next_date_raw, &next_date_fract, &company, &cmd, &cp->err_msg, buffer);
1180 assert(ret == 6);
1181 next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1182 cp->company = (CompanyID)company;
1183 cp->cmd = (Commands)cmd;
1184
1185 /* Parse command data. */
1186 std::vector<uint8_t> args;
1187 size_t arg_len = strlen(buffer);
1188 for (size_t i = 0; i + 1 < arg_len; i += 2) {
1189 uint8_t e = 0;
1190 std::from_chars(buffer + i, buffer + i + 2, e, 16);
1191 args.emplace_back(e);
1192 }
1193 cp->data = args;
1194 } else if (strncmp(p, "join: ", 6) == 0) {
1195 /* Manually insert a pause when joining; this way the client can join at the exact right time. */
1196 uint32_t next_date_raw;
1197 int ret = sscanf(p + 6, "%x; %x", &next_date_raw, &next_date_fract);
1198 next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1199 assert(ret == 2);
1200 Debug(desync, 0, "Injecting pause for join at {:08x}:{:02x}; please join when paused", next_date, next_date_fract);
1201 cp = new CommandPacket();
1203 cp->cmd = CMD_PAUSE;
1205 _ddc_fastforward = false;
1206 } else if (strncmp(p, "sync: ", 6) == 0) {
1207 uint32_t next_date_raw;
1208 int ret = sscanf(p + 6, "%x; %x; %x; %x", &next_date_raw, &next_date_fract, &sync_state[0], &sync_state[1]);
1209 next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
1210 assert(ret == 4);
1211 check_sync_state = true;
1212 } else if (strncmp(p, "msg: ", 5) == 0 || strncmp(p, "client: ", 8) == 0 ||
1213 strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0 ||
1214 strncmp(p, "warning: ", 9) == 0) {
1215 /* A message that is not very important to the log playback, but part of the log. */
1216#ifndef DEBUG_FAILED_DUMP_COMMANDS
1217 } else if (strncmp(p, "cmdf: ", 6) == 0) {
1218 Debug(desync, 0, "Skipping replay of failed command: {}", p + 6);
1219#endif
1220 } else {
1221 /* Can't parse a line; what's wrong here? */
1222 Debug(desync, 0, "Trying to parse: {}", p);
1223 NOT_REACHED();
1224 }
1225 }
1226 if (f.has_value() && feof(*f)) {
1227 Debug(desync, 0, "End of commands.log");
1228 f.reset();
1229 }
1230#endif /* DEBUG_DUMP_COMMANDS */
1232 /* Only check for active clients just before we're going to send out
1233 * the commands so we don't send multiple pause/unpause commands when
1234 * the frame_freq is more than 1 tick. Same with distributing commands. */
1238 }
1239
1240 bool send_frame = false;
1241
1242 /* We first increase the _frame_counter */
1244 /* Update max-frame-counter */
1247 send_frame = true;
1248 }
1249
1251
1252 /* Then we make the frame */
1253 StateGameLoop();
1254
1256#ifdef NETWORK_SEND_DOUBLE_SEED
1257 _sync_seed_2 = _random.state[1];
1258#endif
1259
1260 NetworkServer_Tick(send_frame);
1261 } else {
1262 /* Client */
1263
1264 /* Make sure we are at the frame were the server is (quick-frames) */
1266 /* Run a number of frames; when things go bad, get out. */
1269 }
1270 } else {
1271 /* Else, keep on going till _frame_counter_max */
1273 /* Run one frame; if things went bad, get out. */
1275 }
1276 }
1277 }
1278
1279 NetworkSend();
1280}
1281
1284{
1285 Debug(net, 3, "Starting network");
1286
1287 /* Network is available */
1289 _network_dedicated = false;
1290
1291 _network_game_info = {};
1292
1293 NetworkInitialize();
1295 Debug(net, 3, "Network online, multiplayer available");
1298}
1299
1302{
1306
1307 Debug(net, 3, "Shutting down network");
1308
1309 _network_available = false;
1310
1312}
1313
1314#ifdef __EMSCRIPTEN__
1315extern "C" {
1316
1317void CDECL em_openttd_add_server(const char *connection_string)
1318{
1319 NetworkAddServer(connection_string, false, true);
1320}
1321
1322}
1323#endif
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition address.h:20
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
void SendReceive()
Check whether we received/can send some data from/to the content server and when that's the case hand...
void Register()
Register our server to receive our invite code.
void SendReceive()
Check whether we received/can send some data from/to the Game Coordinator server and when that's the ...
void CloseAllConnections()
Close all pending connection tokens.
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
Class for handling the client side of the game connection.
static ClientNetworkGameSocketHandler * my_client
This is us!
static NetworkRecvStatus SendQuit()
Tell the server we would like to quit.
static bool Receive()
Check whether we received/can send some data from/to the server and when that's the case handle it ap...
static bool GameLoop()
Actual game loop for the client.
static void Send()
Send the packets of this socket handler.
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
Endian-aware buffer adapter that always writes values in little endian order.
Enum-as-bit-set wrapper.
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition address.h:28
static void EnsureValidSecretKeyAndUpdatePublicKey(std::string &secret_key, std::string &public_key)
Ensures that the given secret key is valid, and when not overwrite it with a valid secret key.
bool Contains(std::string_view key) const
Check whether the given key is contains in these authorized keys.
Definition network.cpp:178
bool Add(std::string_view key)
Add the given key to the authorized keys, when it is not already contained.
Definition network.cpp:188
bool Remove(std::string_view key)
Remove the given key from the authorized keys, when it is exists.
Definition network.cpp:204
ClientID client_id
Client identifier.
Definition tcp_game.h:486
static void HTTPReceive()
Do the receiving for all HTTP connections.
static void QueryServer(SOCKET s, const std::string &connection_string)
Start to query a server based on an open socket.
static void SendReceive()
Check if any query needs to send or receive.
std::string connection_string
The connection string for this ServerAddress.
Definition address.h:201
static ServerAddress Parse(const std::string &connection_string, uint16_t default_port, CompanyID *company_id=nullptr)
Convert a string containing either "hostname", "hostname:port" or invite code to a ServerAddress,...
Definition address.cpp:450
Class for handling the server side of the game connection.
static void Send()
Send the packets for the server sockets.
static void WelcomeAll()
Send a Welcome packet to all connected admins.
static Pool::IterateWrapperFiltered< ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter > IterateActive(size_t from=0)
Returns an iterable ensemble of all active admin sockets.
Class for handling the server side of the game connection.
static ServerNetworkGameSocketHandler * GetByClientID(ClientID client_id)
Return the client state given it's client-identifier.
Definition network.cpp:152
static void Send()
Send the packets for the server sockets.
static void AcceptConnection(SOCKET s, const NetworkAddress &address)
Handle the accepting of a connection to the server.
Definition network.cpp:566
NetworkAddress client_address
IP-address of the client (so they can be banned)
Non blocking connection create to actually connect to servers.
Definition network.cpp:743
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition network.cpp:757
void OnFailure() override
Callback for when the connection attempt failed.
Definition network.cpp:750
static void CheckCallbacks()
Check whether we need to call the callback, i.e.
static void KillAll()
Kill all connection attempts.
Non blocking connection to query servers for their game info.
Definition network.cpp:640
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition network.cpp:658
void OnFailure() override
Callback for when the connection attempt failed.
Definition network.cpp:647
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.
const char * GetCommandName(Commands cmd)
This function mask the parameter with CMD_ID_MASK and returns the name which belongs to the given com...
Definition command.cpp:132
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data)
Prepare a DoCommand to be send over the network.
Commands
List of commands.
@ CMD_PAUSE
pause the game
CompanyID GetFirstPlayableCompanyID()
Get the index of the first available company.
CompanyID _current_company
Company currently doing an action.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
static constexpr CompanyID COMPANY_NEW_COMPANY
The client wants a new company.
static const uint16_t NETWORK_DEFAULT_PORT
The default port of the game server (TCP & UDP)
Definition config.h:25
void IConsoleCmdExec(const std::string &command_string, const uint recurse_count)
Execute a given command passed to us.
Definition console.cpp:291
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
static const TextColour CC_DEFAULT
Default colour of the console.
void NetworkCoreShutdown()
Shuts down the network core (as that is needed for some platforms.
Definition core.cpp:44
bool NetworkCoreInitialize()
Initializes the network core (as that is needed for some platforms.
Definition core.cpp:24
@ NETWORK_RECV_STATUS_CLIENT_QUIT
The connection is lost gracefully. Other clients are already informed of this leaving client.
Definition core.h:28
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
@ 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
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, const CommandCost &cc)
Display an error message in a window.
std::optional< FileHandle > FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Definition fileio.cpp:243
@ SAVE_DIR
Base directory for all savegames.
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:50
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
void NetworkFindBroadcastIPs(NetworkAddressList *broadcast)
Find the IPv4 broadcast addresses; IPv6 uses a completely different strategy for broadcasting.
Definition host.cpp:84
Resolving of hostnames/IPs.
void NetworkHTTPInitialize()
Initialize the HTTP socket handler.
void NetworkHTTPUninitialize()
Uninitialize the HTTP socket handler.
uint32_t _last_sync_frame
Used in the server to store the last time a sync packet was sent to clients.
Definition network.cpp:79
void NetworkStartUp()
This tries to launch the network for a given OS.
Definition network.cpp:1283
bool _is_network_server
Does this client wants to be a network-server?
Definition network.cpp:69
NetworkClientInfoPool _networkclientinfo_pool("NetworkClientInfo")
Make sure both pools have the same size.
void NetworkHandlePauseChange(PauseModes prev_mode, PauseMode changed_mode)
Handle the pause mode change so we send the right messages to the chat.
Definition network.cpp:351
static uint NetworkCountActiveClients()
Counts the number of active clients connected.
Definition network.cpp:418
StringList _network_host_list
The servers we know.
Definition network.cpp:74
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
static void CheckPauseOnJoin()
Check whether we should pause on join.
Definition network.cpp:460
NetworkAddressList _broadcast_list
List of broadcast addresses.
Definition network.cpp:80
void NetworkQueryServer(const std::string &connection_string)
Query a server to fetch the game-info.
Definition network.cpp:670
std::string NormalizeConnectionString(const std::string &connection_string, uint16_t default_port)
Normalize a connection string.
Definition network.cpp:539
void NetworkClientJoinGame()
Actually perform the joining to the server.
Definition network.cpp:818
static bool NetworkHasJoiningClient()
Checks whether there is a joining client.
Definition network.cpp:448
static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
Simple helper to find the location of the given authorized key in the authorized keys.
Definition network.cpp:168
ClientID _redirect_console_to_client
If not invalid, redirect the console output to a client.
Definition network.cpp:71
static void CheckClientAndServerName()
Check whether the client and server name are set, for a dedicated server and if not set them to some ...
Definition network.cpp:873
void NetworkOnGameStart()
Perform tasks when the server is started.
Definition network.cpp:945
std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id)
Parse the company part ("#company" postfix) of a connecting string.
Definition network.cpp:475
uint32_t _frame_counter
The current frame.
Definition network.cpp:78
bool _network_available
is network mode available?
Definition network.cpp:67
uint8_t _network_reconnect
Reconnect timeout.
Definition network.cpp:72
bool _networking
are we in networking mode?
Definition network.cpp:65
static void InitializeNetworkPools(bool close_admins=true)
Resets the pools used for network clients, and the admin pool if needed.
Definition network.cpp:581
StringList _network_ban_list
The banned clients.
Definition network.cpp:75
std::string_view ParseFullConnectionString(const std::string &connection_string, uint16_t &port, CompanyID *company_id)
Converts a string to ip/port/company Format: IP:port::company.
Definition network.cpp:519
bool _network_dedicated
are we a dedicated server?
Definition network.cpp:68
bool HasClients()
Return whether there is any client connected or trying to connect at all.
Definition network.cpp:97
static bool NetworkReceive()
Receives something from the network.
Definition network.cpp:1050
NetworkGameList * NetworkAddServer(const std::string &connection_string, bool manually, bool never_expire)
Validates an address entered as a string and adds the server to the list.
Definition network.cpp:692
void NetworkDisconnect(bool close_admins)
We want to disconnect from the host/clients.
Definition network.cpp:999
bool _network_server
network-server is active
Definition network.cpp:66
std::string GenerateUid(std::string_view subject)
Generate an unique ID.
Definition misc.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
void NetworkBackgroundLoop()
We have to do some (simple) background stuff that runs normally, even when we are not in multiplayer.
Definition network.cpp:1080
StringList _network_bind_list
The addresses to bind on.
Definition network.cpp:73
static void CheckMinActiveClients()
Check if the minimum number of active clients has been reached and pause or unpause the game as appro...
Definition network.cpp:434
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:70
static void CheckPauseHelper(bool pause, PauseMode pm)
Helper function for the pause checkers.
Definition network.cpp:406
bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password)
Join a client to the server at with the given connection string.
Definition network.cpp:785
bool _network_first_time
Whether we have finished joining or not.
Definition network.cpp:86
void NetworkShutDown()
This shuts the network down.
Definition network.cpp:1301
uint8_t _network_clients_connected
The amount of clients connected.
Definition network.cpp:89
void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
Get the addresses to bind to.
Definition network.cpp:718
NetworkAddress ParseConnectionString(const std::string &connection_string, uint16_t default_port)
Convert a string containing either "hostname" or "hostname:ip" to a NetworkAddress.
Definition network.cpp:554
void NetworkUpdateServerGameType()
The setting server_game_type was updated; possibly we need to take some action.
Definition network.cpp:1027
bool NetworkCanJoinCompany(CompanyID company_id)
Returns whether the given company can be joined by this client.
Definition network.cpp:141
void NetworkClose(bool close_admins)
Close current connections.
Definition network.cpp:592
uint32_t _frame_counter_max
To where we may go with our clients.
Definition network.cpp:77
bool NetworkValidateServerName(std::string &server_name)
Trim the given server name in place, i.e.
Definition network.cpp:858
Server part of the admin network protocol.
Base core network types and some helper functions to access them.
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message)
Add a text message to the 'chat window' to be shown.
NetworkJoinInfo _network_join
Information about the game to join to.
bool NetworkValidateOurClientName()
Convenience method for NetworkValidateClientName on _settings_client.network.client_name.
void NetworkClient_Connected()
Is called after a client is connected to the server.
Client part of the network protocol.
void NetworkFreeLocalCommandQueue()
Free the local command queues.
void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
void NetworkDistributeCommands()
Distribute the commands of ourself and the clients.
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
Part of the network protocol handling content distribution.
ClientNetworkCoordinatorSocketHandler _network_coordinator_client
The connection to the Game Coordinator.
Part of the network protocol handling Game Coordinator requests.
void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci)
Perform all the server specific administration of a new company.
void NetworkServerUpdateGameInfo()
Update the server's NetworkServerGameInfo due to changes in settings.
NetworkGameList * NetworkGameListAddItem(const std::string &connection_string)
Add a new item to the linked gamelist.
NetworkGameList * _network_game_list
Game list of this client.
Handling of the list of games.
@ NGLS_OFFLINE
Server is offline (or cannot be queried).
NetworkJoinStatus _network_join_status
The status of joining.
void UpdateNetworkGameWindow()
Update the network new window because a new server is found on the network.
GUIs related to networking.
Query part of the network protocol.
void ChangeNetworkRestartTime(bool reset)
Reset the automatic network restart time interval.
void NetworkServer_Tick(bool send_frame)
This is called every tick if this is a _network_server.
Server part of the network protocol.
@ DESTTYPE_CLIENT
Send message/notice to only a certain client (Private)
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.
void NetworkUDPClose()
Close all UDP related stuff.
void NetworkUDPInitialize()
Initialize the whole UDP bit.
void NetworkUDPServerListen()
Start the listening of the UDP server component.
void NetworkBackgroundUDPLoop()
Receive the UDP packets.
Sending and receiving UDP messages.
void ClearGRFConfigList(GRFConfigList &config)
Clear a GRF Config list, freeing all nodes.
void StateGameLoop()
State controlling game loop.
Definition openttd.cpp:1206
PauseMode
Modes of pausing we've got.
Definition openttd.h:68
@ LinkGraph
A game paused due to the link graph schedule lagging.
@ Error
A game paused because a (critical) error.
@ GameScript
A game paused by a game script.
@ ActiveClients
A game paused for 'min_active_clients'.
@ Normal
A game normally paused.
@ Join
A game paused for 'pause_on_join'.
@ SM_JOIN_GAME
Join a network game.
Definition openttd.h:41
@ SM_MENU
Switch to game intro menu.
Definition openttd.h:33
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
@ NetworkClient
Network client pools.
@ NetworkAdmin
Network admin pool.
Randomizer _random
Random used in the game state calculations.
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
bool StrEqualsIgnoreCase(const std::string_view str1, const std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:365
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
size_t Utf8Encode(T buf, char32_t c)
Encode a unicode character and place it in the buffer.
Definition string.cpp:478
static const char32_t CHAR_TD_LRM
The next character acts like a left-to-right character.
Definition string_type.h:35
static const char32_t CHAR_TD_RLM
The next character acts like a right-to-left character.
Definition string_type.h:36
std::vector< std::string > StringList
Type for a list of strings.
Definition string_type.h:60
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Definition strings.cpp:338
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
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_LTR
Text is written left-to-right by default.
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.
StringID err_msg
string ID of error message to use.
CommandDataBuffer data
command parameters.
CompanyID company
company that is executing the command
Commands cmd
command being executed.
Defines the traits of a command.
NetworkAuthorizedKeys allow_list
Public keys of clients that are allowed to join this company.
StringID name_1
Name of the company if the user did not change it.
std::string name
Name of the company if the user changed it.
uint16_t network_chat_timeout
timeout of chat messages in seconds
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
~NetworkClientInfo()
Basically a client is leaving us right now.
Definition network.cpp:105
bool CanJoinCompany(CompanyID company_id) const
Returns whether the given company can be joined by this client.
Definition network.cpp:130
CompanyID client_playas
As which company is this client playing (CompanyID)
ClientID client_id
Client identifier (same as ClientState->client_id)
std::string client_name
Name of the client.
std::string public_key
The public key of the client.
Structure with information shown in the game list (GUI)
int version
Used to see which servers are no longer available on the Game Coordinator and can be removed.
bool refreshing
Whether this server is being queried.
bool manually
True if the server was added manually.
NetworkGameList * next
Next pointer to make a linked game list.
NetworkGameListStatus status
Stats of the server.
NetworkGameInfo info
The game information of this server.
std::string connection_string
The address of the server to join.
std::string server_password
The password of the server to join.
CompanyID company
The company to join.
GRFConfigList grfconfig
List of NewGRF files used.
std::string server_name
Server name.
uint8_t clients_on
Current count of clients on server.
std::string client_secret_key
The secret key of the client for authorized key logins.
std::string client_name
name of the player (as client)
ServerGameType server_game_type
Server type: local / public / invite-only.
std::string client_public_key
The public key of the client for authorized key logins.
uint8_t frame_freq
how often do we send commands to the clients
uint8_t min_active_clients
minimum amount of active clients to unpause the game
uint16_t server_port
port the server listens on
std::string last_joined
Last joined server.
std::string server_name
name of the server
uint16_t server_admin_port
port the server listens on for the admin network
bool pause_on_join
pause the game when people join
static void Clean(PoolTypes)
Clean all pools of given type.
Definition pool_func.cpp:30
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Tindex index
Index of this pool item.
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.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Base class for all pools.
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
uint32_t state[2]
The state of the randomizer.
The data required to format and validate a single parameter of a string.
Basic functions to receive and send UDP packets.
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
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition window_type.h:41
@ WC_SEND_NETWORK_MSG
Chatbox; Window numbers:
@ WC_CLIENT_LIST
Client list; Window numbers:
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers: