12#include "../../stdafx.h"
13#include "network_game_info.h"
14#include "../../core/bitmath_func.hpp"
15#include "../../company_base.h"
16#include "../../timer/timer_game_calendar.h"
17#include "../../timer/timer_game_tick.h"
18#include "../../debug.h"
19#include "../../map_func.h"
20#include "../../game/game.hpp"
21#include "../../game/game_info.hpp"
22#include "../../settings_type.h"
23#include "../../string_func.h"
25#include "../network_func.h"
26#include "../network.h"
27#include "../network_internal.h"
30#include "../../safeguards.h"
37static const uint GITHASH_SUFFIX_LEN = 12;
45std::string_view GetNetworkRevisionString()
47 static std::string network_revision;
49 if (network_revision.empty()) {
50#if not defined(NETWORK_INTERNAL_H)
51# error("network_internal.h must be included, otherwise the debug related preprocessor tokens won't be picked up correctly.")
52#elif not defined(ENABLE_NETWORK_SYNC_EVERY_FRAME)
54 network_revision = _openttd_revision;
55#elif defined(NETWORK_SEND_DOUBLE_SEED)
57 network_revision = fmt::format(
"dbg_seed-{}", _openttd_revision);
60 network_revision = fmt::format(
"dbg_sync-{}", _openttd_revision);
62 if (_openttd_revision_tagged) {
67 assert(_openttd_revision_modified < 3);
68 std::string githash_suffix = fmt::format(
"-{}{}",
"gum"[_openttd_revision_modified], _openttd_revision_hash);
69 if (githash_suffix.size() > GITHASH_SUFFIX_LEN) githash_suffix.resize(GITHASH_SUFFIX_LEN);
72 size_t hash_end = network_revision.find_last_of(
'-');
73 if (hash_end == std::string::npos) hash_end = network_revision.size();
77 network_revision.replace(hash_end, std::string::npos, githash_suffix);
80 Debug(net, 3,
"Network revision name: {}", network_revision);
83 return network_revision;
91static std::string_view ExtractNetworkRevisionHash(std::string_view revision_string)
93 size_t index = revision_string.find_last_of(
'-');
94 if (index == std::string::npos)
return {};
95 return revision_string.substr(index);
103bool IsNetworkCompatibleVersion(std::string_view other)
105 std::string_view our_revision = GetNetworkRevisionString();
106 if (our_revision == other)
return true;
111 if (_openttd_revision_tagged)
return false;
114 if (other.starts_with(
"dbg_seed") != our_revision.starts_with(
"dbg_seed"))
return false;
115 if (other.starts_with(
"dbg_sync") != our_revision.starts_with(
"dbg_sync"))
return false;
117 std::string_view hash1 = ExtractNetworkRevisionHash(our_revision);
118 std::string_view hash2 = ExtractNetworkRevisionHash(other);
119 return hash1 == hash2;
132 for (
const auto &c : ngi.grfconfig) {
141void FillStaticNetworkServerGameInfo()
172 return _network_game_info;
183static void HandleIncomingNetworkGameInfoGRFConfig(
GRFConfig &config, std::string_view name)
220 p.
Send_uint8(send_newgrf_names ? NST_GRFID_MD5_NAME : NST_GRFID_MD5);
224 p.
Send_uint32(game_info ==
nullptr ? -1 : (uint32_t)game_info->GetVersion());
225 p.
Send_string(game_info ==
nullptr ?
"" : game_info->GetName());
233 uint count = std::ranges::count_if(info.
grfconfig, [](
const auto &c) { return !c->flags.Test(GRFConfigFlag::Static); });
237 for (
const auto &c : info.grfconfig) {
240 SerializeGRFIdentifier(p, c->ident);
241 if (send_newgrf_names) p.
Send_string(c->GetName());
272void DeserializeNetworkGameInfo(
Packet &p,
NetworkGameInfo &info,
const GameInfoNewGRFLookupTable *newgrf_lookup_table)
275 NewGRFSerializationType newgrf_serialisation = NST_GRFID_MD5;
285 switch (game_info_version) {
291 newgrf_serialisation = (NewGRFSerializationType)p.
Recv_uint8();
292 if (newgrf_serialisation >= NST_END)
return;
309 for (uint i = 0; i < num_grfs; i++) {
311 switch (newgrf_serialisation) {
313 DeserializeGRFIdentifier(p, grf.
ident);
316 case NST_GRFID_MD5_NAME:
317 DeserializeGRFIdentifierWithName(p, grf);
320 case NST_LOOKUP_ID: {
321 if (newgrf_lookup_table ==
nullptr)
return;
322 auto it = newgrf_lookup_table->find(p.
Recv_uint32());
323 if (it == newgrf_lookup_table->end())
return;
332 auto c = std::make_unique<GRFConfig>();
333 c->ident = grf.
ident;
334 HandleIncomingNetworkGameInfoGRFConfig(*c, grf.
name);
337 dst.push_back(std::move(c));
361 if (game_info_version < 3) {
365 if (game_info_version < 6)
while (p.
Recv_uint8() != 0) {}
375 if (game_info_version < 7) {
409 DeserializeGRFIdentifier(p, grf.
ident);
constexpr Timpl & Set()
Set all bits.
All static information from an Game like name, version, etc.
static class GameInfo * GetInfo()
Get the current GameInfo.
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 ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
static Date date
Current date in days (day counter).
static constexpr TimerGame< struct Calendar >::Date MAX_DATE
The date of the last day of the max year.
static constexpr TimerGame< struct Calendar >::Date DAYS_TILL_ORIGINAL_BASE_YEAR
The date of the first day of the original base year.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including '\0'.
static const uint NETWORK_GRF_NAME_LENGTH
Maximum length of the name of a GRF.
static const uint NETWORK_MAX_GRF_COUNT
Maximum number of GRFs that can be sent.
static const uint NETWORK_REVISION_LENGTH
The maximum length of the revision, in bytes including '\0'.
static const uint8_t NETWORK_GAME_INFO_VERSION
What version of game-info do we use?
#define Debug(category, level, format_string,...)
Output a line of debugging information.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
LandscapeType
Landscape types.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
bool _network_dedicated
are we a dedicated server?
GRFConfigList _grfconfig
First item in list of current GRF set up.
void CopyGRFConfigList(GRFConfigList &dst, const GRFConfigList &src, bool init_only)
Copy a GRF Config list.
const GRFConfig * FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
@ GCS_NOT_FOUND
GRF file was not found in the local cache.
@ Copy
The data is copied from a grf in _all_grfs.
@ Static
GRF file is used statically (can be used in any MP game)
@ FGCM_EXACT
Only find Grfs matching md5sum.
static void AddGRFTextToList(GRFTextList &list, uint8_t langid, std::string_view text_to_add)
Add a new text to a GRFText list.
Basic functions to create, fill and read packets.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
ClientSettings _settings_client
The current settings for this game.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
NetworkSettings network
settings related to the network
Information about GRF, used in the game and (part of it) in savegames.
GRFTextWrapper url
NOSAVE: URL belonging to this GRF.
GRFTextWrapper info
NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
GRFTextWrapper name
NOSAVE: GRF name (Action 0x08)
GRFStatus status
NOSAVE: GRFStatus, enum.
GRFConfigFlags flags
NOSAVE: GCF_Flags, bitset.
std::string filename
Filename - either with or without full path.
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
Basic data to distinguish a GRF.
uint32_t grfid
GRF ID (defined by Action 0x08)
MD5Hash md5sum
MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
LandscapeType landscape
the landscape we're currently in
TimerGameCalendar::Year starting_year
starting date
GameCreationSettings game_creation
settings used during the creation of a game (map)
static uint SizeY()
Get the size of the map along the Y.
static debug_inline uint SizeX()
Get the size of the map along the X.
Container to hold the GRF identifier (GRF ID + MD5 checksum) and the name associated with that NewGRF...
std::string name
The name of the NewGRF.
GRFIdentifier ident
The unique identifier of the NewGRF.
The game information that is sent from the server to the clients with extra information only required...
bool version_compatible
Can we connect to this server or not? (based on server_revision)
bool compatible
Can we connect to this server or not? (based on server_revision and grf_match.
The game information that is sent from the server to the client.
TimerGameCalendar::Date calendar_start
When the game started.
bool dedicated
Is this a dedicated server?
std::string server_revision
The version number the server is using (e.g.: 'r304' or 0.5.0)
bool use_password
Is this server passworded?
uint8_t clients_max
Max clients allowed on server.
uint8_t spectators_on
How many spectators do we have?
GRFConfigList grfconfig
List of NewGRF files used.
uint16_t map_height
Map height.
std::string server_name
Server name.
uint16_t map_width
Map width.
TimerGameTick::TickCounter ticks_playing
Amount of ticks the game has been running unpaused.
LandscapeType landscape
The used landscape.
uint8_t companies_max
Max companies allowed on server.
std::string gamescript_name
Name of the gamescript.
TimerGameCalendar::Date calendar_date
Current calendar date.
int gamescript_version
Version of the gamescript.
uint8_t companies_on
How many started companies do we have.
uint8_t clients_on
Current count of clients on server.
uint8_t max_clients
maximum amount of clients
uint8_t max_companies
maximum amount of companies
std::string server_name
name of the server
std::string server_password
password for joining this server
Internal entity of a packet.
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
size_t Recv_bytes(std::span< uint8_t > span)
Extract at most the length of the span bytes from the packet into the span.
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
bool Recv_bool()
Read a boolean from the packet.
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
void Send_bool(bool data)
Package a boolean in the packet.
std::span< const uint8_t > Send_bytes(const std::span< const uint8_t > span)
Send as many of the bytes as possible in the packet.
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
void Send_uint8(uint8_t data)
Package a 8 bits integer in the packet.
void Send_uint32(uint32_t data)
Package a 32 bits integer in the packet.
void Send_uint16(uint16_t data)
Package a 16 bits integer in the packet.
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
void Send_string(const std::string_view data)
Sends a string over the network.
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
static size_t GetNumItems()
Returns number of valid items in the pool.