OpenTTD Source 20260421-master-gc2fbc6fdeb
survey.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
9
10#include "stdafx.h"
11
12#include "survey.h"
13
14#include "settings_table.h"
15#include "network/network.h"
16#include "rev.h"
17#include "settings_type.h"
21#include "3rdparty/fmt/ranges.h"
22
23#include "currency.h"
24#include "fontcache.h"
25#include "language.h"
26
27#include "ai/ai_info.hpp"
28#include "game/game.hpp"
29#include "game/game_info.hpp"
30
34
35#include "base_media_base.h"
36#include "base_media_graphics.h"
37#include "base_media_music.h"
38#include "base_media_sounds.h"
39#include "blitter/factory.hpp"
40
41#include "social_integration.h"
42
43#ifdef WITH_ALLEGRO
44# include <allegro.h>
45#endif /* WITH_ALLEGRO */
46#ifdef WITH_FONTCONFIG
47# include <fontconfig/fontconfig.h>
48#endif /* WITH_FONTCONFIG */
49#ifdef WITH_PNG
50 /* pngconf.h, included by png.h doesn't like something in the
51 * freetype headers. As such it's not alphabetically sorted. */
52# include <png.h>
53#endif /* WITH_PNG */
54#ifdef WITH_FREETYPE
55# include <ft2build.h>
56# include FT_FREETYPE_H
57#endif /* WITH_FREETYPE */
58#ifdef WITH_HARFBUZZ
59# include <hb.h>
60#endif /* WITH_HARFBUZZ */
61#ifdef WITH_ICU_I18N
62# include <unicode/uversion.h>
63#endif /* WITH_ICU_I18N */
64#ifdef WITH_LIBLZMA
65# include <lzma.h>
66#endif
67#ifdef WITH_LZO
68#include <lzo/lzo1x.h>
69#endif
70#ifdef WITH_SDL2
71#include <SDL.h>
72#endif /* WITH_SDL2 */
73#ifdef WITH_ZLIB
74# include <zlib.h>
75#endif
76#ifdef WITH_CURL
77# include <curl/curl.h>
78#endif
79
80#include "safeguards.h"
81
82#ifndef DOXYGEN_API
83
84NLOHMANN_JSON_SERIALIZE_ENUM(GRFStatus, {
85 {GRFStatus::Unknown, "unknown"},
86 {GRFStatus::Disabled, "disabled"},
87 {GRFStatus::NotFound, "not found"},
88 {GRFStatus::Initialised, "initialised"},
89 {GRFStatus::Activated, "activated"},
90})
91
92NLOHMANN_JSON_SERIALIZE_ENUM(SocialIntegrationPlugin::State, {
100})
101
102#endif /* DOXYGEN_API */
103
105static const std::string _vehicle_type_to_string[] = {
106 "train",
107 "roadveh",
108 "ship",
109 "aircraft",
110};
111
124{
125 static const SettingTable _generic_setting_tables[] = {
126 _difficulty_settings,
127 _economy_settings,
128 _game_settings,
129 _gui_settings,
130 _linkgraph_settings,
131 _locale_settings,
132 _multimedia_settings,
133 _network_settings,
134 _news_display_settings,
135 _pathfinding_settings,
136 _script_settings,
137 _world_settings,
138 };
139 return _generic_setting_tables;
140}
141
150static void SurveySettingsTable(nlohmann::json &survey, const SettingTable &table, void *object, bool skip_if_default)
151{
152 for (auto &desc : table) {
153 const SettingDesc *sd = GetSettingDesc(desc);
154 /* Skip any old settings we no longer save/load. */
156
157 const auto &name = sd->GetName();
158 if (skip_if_default && sd->IsDefaultValue(object)) continue;
159 survey[name] = sd->FormatValue(object);
160 }
161}
162
169void SurveySettings(nlohmann::json &survey, bool skip_if_default)
170{
171 SurveySettingsTable(survey, _misc_settings, nullptr, skip_if_default);
172#if defined(_WIN32) && !defined(DEDICATED)
173 SurveySettingsTable(survey, _win32_settings, nullptr, skip_if_default);
174#endif
175 for (auto &table : GenericSettingTables()) {
176 SurveySettingsTable(survey, table, &_settings_game, skip_if_default);
177 }
178 SurveySettingsTable(survey, _currency_settings, &GetCustomCurrency(), skip_if_default);
179 SurveySettingsTable(survey, _company_settings, &_settings_client.company, skip_if_default);
180}
181
187void SurveyCompiler(nlohmann::json &survey)
188{
189#if defined(_MSC_VER)
190 survey["name"] = "MSVC";
191 survey["version"] = _MSC_VER;
192#elif defined(__ICC) && defined(__GNUC__)
193 survey["name"] = "ICC";
194 survey["version"] = __ICC;
195# if defined(__GNUC__)
196 survey["extra"] = fmt::format("GCC {}.{}.{} mode", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
197# endif
198#elif defined(__GNUC__)
199 survey["name"] = "GCC";
200 survey["version"] = fmt::format("{}.{}.{}", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
201#else
202 survey["name"] = "unknown";
203#endif
204
205#if defined(__VERSION__)
206 survey["extra"] = __VERSION__;
207#endif
208}
209
215void SurveyOpenTTD(nlohmann::json &survey)
216{
217 survey["version"]["revision"] = std::string(_openttd_revision);
218 survey["version"]["modified"] = _openttd_revision_modified;
219 survey["version"]["tagged"] = _openttd_revision_tagged;
220 survey["version"]["hash"] = std::string(_openttd_revision_hash);
221 survey["version"]["newgrf"] = fmt::format("{:X}", _openttd_newgrf_version);
222 survey["version"]["content"] = std::string(_openttd_content_version);
223 survey["build_date"] = std::string(_openttd_build_date);
224 survey["bits"] =
225#ifdef POINTER_IS_64BIT
226 64
227#else
228 32
229#endif
230 ;
231 if constexpr (std::endian::native == std::endian::little) survey["endian"] = "little";
232 if constexpr (std::endian::native == std::endian::big) survey["endian"] = "big";
233 survey["dedicated_build"] =
234#ifdef DEDICATED
235 "yes"
236#else
237 "no"
238#endif
239 ;
240}
241
247void SurveyGameSession(nlohmann::json &survey)
248{
249 survey["id"] = _game_session_stats.savegame_id;
250 survey["seconds"] = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - _game_session_stats.start_time).count();
251 if (_game_session_stats.savegame_size.has_value()) {
252 survey["savegame_size"] = _game_session_stats.savegame_size.value();
253 }
254}
255
261void SurveyConfiguration(nlohmann::json &survey)
262{
263 survey["network"] = _networking ? (_network_server ? "server" : "client") : "no";
264 if (_current_language != nullptr) {
265 survey["language"]["filename"] = FS2OTTD(_current_language->file.filename().native());
266 survey["language"]["name"] = _current_language->name;
267 survey["language"]["isocode"] = _current_language->isocode;
268 }
269 if (BlitterFactory::GetCurrentBlitter() != nullptr) {
270 survey["blitter"] = BlitterFactory::GetCurrentBlitter()->GetName();
271 }
272 if (MusicDriver::GetInstance() != nullptr) {
273 survey["music_driver"] = MusicDriver::GetInstance()->GetName();
274 }
275 if (SoundDriver::GetInstance() != nullptr) {
276 survey["sound_driver"] = SoundDriver::GetInstance()->GetName();
277 }
278 if (VideoDriver::GetInstance() != nullptr) {
279 survey["video_driver"] = VideoDriver::GetInstance()->GetName();
280 survey["video_info"] = VideoDriver::GetInstance()->GetInfoString();
281 }
282 if (BaseGraphics::GetUsedSet() != nullptr) {
283 survey["graphics_set"] = fmt::format("{}.{}", BaseGraphics::GetUsedSet()->name, fmt::join(BaseGraphics::GetUsedSet()->version, "."));
284 const GRFConfig *extra_cfg = BaseGraphics::GetUsedSet()->GetExtraConfig();
285 if (extra_cfg != nullptr && !extra_cfg->param.empty()) {
286 survey["graphics_set_parameters"] = std::span<const uint32_t>(extra_cfg->param);
287 } else {
288 survey["graphics_set_parameters"] = std::span<const uint32_t>();
289 }
290 }
291 if (BaseMusic::GetUsedSet() != nullptr) {
292 survey["music_set"] = fmt::format("{}.{}", BaseMusic::GetUsedSet()->name, fmt::join(BaseMusic::GetUsedSet()->version, "."));
293 }
294 if (BaseSounds::GetUsedSet() != nullptr) {
295 survey["sound_set"] = fmt::format("{}.{}", BaseSounds::GetUsedSet()->name, fmt::join(BaseSounds::GetUsedSet()->version, "."));
296 }
297}
298
304void SurveyFont(nlohmann::json &survey)
305{
306 survey["small"] = FontCache::Get(FontSize::Small)->GetFontName();
307 survey["medium"] = FontCache::Get(FontSize::Normal)->GetFontName();
308 survey["large"] = FontCache::Get(FontSize::Large)->GetFontName();
310}
311
317void SurveyCompanies(nlohmann::json &survey)
318{
319 for (const Company *c : Company::Iterate()) {
320 auto &company = survey[fmt::format("{}", c->index.base())];
321 if (c->ai_info == nullptr) {
322 company["type"] = "human";
323 } else {
324 company["type"] = "ai";
325 company["script"] = fmt::format("{}.{}", c->ai_info->GetName(), c->ai_info->GetVersion());
326 }
327
328 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
329 uint amount = c->group_all[type].num_vehicle;
330 company["vehicles"][_vehicle_type_to_string[type]] = amount;
331 }
332
333 company["infrastructure"]["road"] = c->infrastructure.GetRoadTotal();
334 company["infrastructure"]["tram"] = c->infrastructure.GetTramTotal();
335 company["infrastructure"]["rail"] = c->infrastructure.GetRailTotal();
336 company["infrastructure"]["signal"] = c->infrastructure.signal;
337 company["infrastructure"]["water"] = c->infrastructure.water;
338 company["infrastructure"]["station"] = c->infrastructure.station;
339 company["infrastructure"]["airport"] = c->infrastructure.airport;
340 }
341}
342
348void SurveyTimers(nlohmann::json &survey)
349{
350 survey["ticks"] = TimerGameTick::counter;
351
352 TimerGameEconomy::YearMonthDay economy_ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
353 survey["economy"] = fmt::format("{:04}-{:02}-{:02} ({})", economy_ymd.year, economy_ymd.month + 1, economy_ymd.day, TimerGameEconomy::date_fract);
354
355 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
356 survey["calendar"] = fmt::format("{:04}-{:02}-{:02} ({})", ymd.year, ymd.month + 1, ymd.day, TimerGameCalendar::date_fract);
357}
358
364void SurveyGrfs(nlohmann::json &survey)
365{
366 for (const auto &c : _grfconfig) {
367 auto grfid = fmt::format("{:08x}", std::byteswap(c->ident.grfid));
368 auto &grf = survey[std::move(grfid)];
369
370 grf["md5sum"] = FormatArrayAsHex(c->ident.md5sum);
371 grf["status"] = c->status;
372
373 if ((c->palette & GRFP_GRF_MASK) == GRFP_GRF_UNSET) grf["palette"] = "unset";
374 if ((c->palette & GRFP_GRF_MASK) == GRFP_GRF_DOS) grf["palette"] = "dos";
375 if ((c->palette & GRFP_GRF_MASK) == GRFP_GRF_WINDOWS) grf["palette"] = "windows";
376 if ((c->palette & GRFP_GRF_MASK) == GRFP_GRF_ANY) grf["palette"] = "any";
377
378 if ((c->palette & GRFP_BLT_MASK) == GRFP_BLT_UNSET) grf["blitter"] = "unset";
379 if ((c->palette & GRFP_BLT_MASK) == GRFP_BLT_32BPP) grf["blitter"] = "32bpp";
380
381 grf["is_static"] = c->flags.Test(GRFConfigFlag::Static);
382 grf["parameters"] = std::span<const uint32_t>(c->param);
383 }
384}
385
391void SurveyGameScript(nlohmann::json &survey)
392{
393 if (Game::GetInfo() == nullptr) return;
394
395 survey = fmt::format("{}.{}", Game::GetInfo()->GetName(), Game::GetInfo()->GetVersion());
396}
397
403void SurveyLibraries(nlohmann::json &survey)
404{
405#ifdef WITH_ALLEGRO
406 survey["allegro"] = std::string(allegro_id);
407#endif /* WITH_ALLEGRO */
408
409#ifdef WITH_FONTCONFIG
410 int version = FcGetVersion();
411 survey["fontconfig"] = fmt::format("{}.{}.{}", version / 10000, (version / 100) % 100, version % 100);
412#endif /* WITH_FONTCONFIG */
413
414#ifdef WITH_FREETYPE
415 FT_Library library;
416 int major, minor, patch;
417 FT_Init_FreeType(&library);
418 FT_Library_Version(library, &major, &minor, &patch);
419 FT_Done_FreeType(library);
420 survey["freetype"] = fmt::format("{}.{}.{}", major, minor, patch);
421#endif /* WITH_FREETYPE */
422
423#if defined(WITH_HARFBUZZ)
424 survey["harfbuzz"] = hb_version_string();
425#endif /* WITH_HARFBUZZ */
426
427#if defined(WITH_ICU_I18N)
428 /* 4 times 0-255, separated by dots (.) and a trailing '\0' */
429 char buf[4 * 3 + 3 + 1];
430 UVersionInfo ver;
431 u_getVersion(ver);
432 u_versionToString(ver, buf);
433 survey["icu_i18n"] = buf;
434#endif /* WITH_ICU_I18N */
435
436#ifdef WITH_LIBLZMA
437 survey["lzma"] = lzma_version_string();
438#endif
439
440#ifdef WITH_LZO
441 survey["lzo"] = lzo_version_string();
442#endif
443
444#ifdef WITH_PNG
445 survey["png"] = png_get_libpng_ver(nullptr);
446#endif /* WITH_PNG */
447
448#ifdef WITH_SDL2
449 SDL_version sdl2_v;
450 SDL_GetVersion(&sdl2_v);
451 survey["sdl2"] = fmt::format("{}.{}.{}", sdl2_v.major, sdl2_v.minor, sdl2_v.patch);
452#endif
453
454#ifdef WITH_ZLIB
455 survey["zlib"] = zlibVersion();
456#endif
457
458#ifdef WITH_CURL
459 auto *curl_v = curl_version_info(CURLVERSION_NOW);
460 survey["curl"] = curl_v->version;
461 survey["curl_ssl"] = curl_v->ssl_version == nullptr ? "none" : curl_v->ssl_version;
462#endif
463}
464
470void SurveyPlugins(nlohmann::json &survey)
471{
473
474 for (auto &plugin : _plugins) {
475 auto &platform = survey[plugin->social_platform];
476 platform.push_back({
477 {"name", plugin->name},
478 {"version", plugin->version},
479 {"basepath", plugin->basepath},
480 {"state", plugin->state},
481 });
482 }
483}
484
493std::string SurveyMemoryToText(uint64_t memory)
494{
495 memory = memory / 1024; // KiB
496 memory = CeilDiv(memory, 1024); // MiB
497
498 /* Anything above 512 MiB we represent in GiB. */
499 if (memory > 512) {
500 return fmt::format("{} GiB", CeilDiv(memory, 1024));
501 }
502
503 /* Anything above 64 MiB we represent in a multiplier of 128 MiB. */
504 if (memory > 64) {
505 return fmt::format("{} MiB", Ceil(memory, 128));
506 }
507
508 /* Anything else in a multiplier of 4 MiB. */
509 return fmt::format("{} MiB", Ceil(memory, 4));
510}
AIInfo keeps track of all information of an AI, like Author, Description, ...
Generic functions for replacing base data (graphics, sounds).
Generic functions for replacing base graphics data.
Generic functions for replacing base music data.
Generic functions for replacing base sounds data.
constexpr enable_if_t< is_integral_v< T >, T > byteswap(T x) noexcept
Custom implementation of std::byteswap; remove once we build with C++23.
static const GraphicsSet * GetUsedSet()
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:139
virtual std::string_view GetName()=0
Get the name of the blitter, the same as the Factory-instance returns.
virtual std::string_view GetName() const =0
Get the name of this driver.
virtual std::string GetFontName()=0
Get the name of this font.
static FontCache * Get(FontSize fs)
Get the font cache of a given font size.
Definition fontcache.h:136
static class GameInfo * GetInfo()
Get the current GameInfo.
Definition game.hpp:73
static MusicDriver * GetInstance()
Get the currently active instance of the music driver.
@ PLATFORM_NOT_RUNNING
The plugin failed to initialize because the Social Platform is not running.
@ UNSUPPORTED_API
The plugin does not support the current API version.
@ RUNNING
The plugin is successfully loaded and running.
@ FAILED
The plugin failed to initialize.
@ DUPLICATE
Another plugin of the same Social Platform is already loaded.
@ INVALID_SIGNATURE
The signature of the plugin is invalid.
@ UNLOADED
The plugin is unloaded upon request.
static std::vector< SocialIntegrationPlugin * > GetPlugins()
Get the list of loaded social integration plugins.
static SoundDriver * GetInstance()
Get the currently active instance of the sound driver.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
virtual std::string_view GetInfoString() const
Get some information about the selected driver/backend to be shown to the user.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
Functions to handle different currencies.
CurrencySpec & GetCustomCurrency()
Get the custom currency.
Definition currency.h:110
Factory to 'query' all available blitters.
Functions to read fonts from files and cache them.
Base functions for all Games.
GameInfo keeps track of all information of an Game, like Author, Description, ...
GameSessionStats _game_session_stats
Statistics about the current session.
Definition gfx.cpp:52
@ Small
Index of the small font in the font tables.
Definition gfx_type.h:250
@ Large
Index of the large font in the font tables.
Definition gfx_type.h:251
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
@ Monospace
Index of the monospaced font in the font tables.
Definition gfx_type.h:252
Information about languages and their files.
const LanguageMetadata * _current_language
The currently loaded language.
Definition strings.cpp:54
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr uint Ceil(uint a, uint b)
Computes ceil(a / b) * b for non-negative a and b.
Base for all music playback.
bool _networking
are we in networking mode?
Definition network.cpp:67
bool _network_server
network-server is active
Definition network.cpp:68
Basic functions/variables used all over the place.
GRFConfigList _grfconfig
First item in list of current GRF set up.
GRFStatus
Status of GRF.
@ NotFound
GRF file was not found in the local cache.
@ Initialised
GRF file has been initialised.
@ Unknown
The status of this grf file is unknown.
@ Disabled
GRF file is disabled.
@ Activated
GRF file has been activated.
@ Static
GRF file is used statically (can be used in any MP game).
@ GRFP_GRF_UNSET
The NewGRF provided no information.
@ GRFP_BLT_UNSET
The NewGRF provided no information or doesn't care about a 32 bpp blitter.
@ GRFP_GRF_WINDOWS
The NewGRF says the Windows palette can be used.
@ GRFP_GRF_DOS
The NewGRF says the DOS palette can be used.
@ GRFP_GRF_ANY
The NewGRF says any palette can be used.
@ GRFP_BLT_MASK
Bitmask to only get the blitter information.
@ GRFP_BLT_32BPP
The NewGRF prefers a 32 bpp blitter.
@ GRFP_GRF_MASK
Bitmask to get only the NewGRF supplied information.
Declaration of OTTD revision dependent variables.
A number of safeguards to prevent using unsafe methods.
bool SlIsObjectCurrentlyValid(SaveLoadVersion version_from, SaveLoadVersion version_to)
Checks if some version from/to combination falls within the range of the active savegame version.
Definition saveload.h:1331
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
static constexpr const SettingDesc * GetSettingDesc(const SettingVariant &desc)
Helper to convert the type of the iterated settings description to a pointer to it.
Definition of the configuration tables of the settings.
Types related to global configuration settings.
static std::vector< std::unique_ptr< InternalSocialIntegrationPlugin > > _plugins
List of loaded plugins.
Interface definitions for game to report/respond to social integration.
Base for all sound drivers.
Definition of base types and functions in a cross-platform compatible way.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition string.cpp:77
Information about GRF, used in the game and (part of it) in savegames.
std::vector< uint32_t > param
GRF parameters.
static Pool::IterateWrapper< Company > Iterate(size_t from=0)
SaveLoadVersion version_to
Save/load the variable before this savegame version.
Definition saveload.h:764
SaveLoadVersion version_from
Save/load the variable starting from this savegame version.
Definition saveload.h:763
Properties of config file settings.
constexpr const std::string & GetName() const
Get the name of this setting.
virtual std::string FormatValue(const void *object) const =0
Format the value of the setting associated with this object.
virtual bool IsDefaultValue(void *object) const =0
Check whether the value is the same as the default value.
SaveLoad save
Internal structure (going to savegame, parts to config).
void SurveySettings(nlohmann::json &survey, bool skip_if_default)
Convert settings to JSON.
Definition survey.cpp:169
void SurveyPlugins(nlohmann::json &survey)
Convert plugin information to JSON.
Definition survey.cpp:470
void SurveyTimers(nlohmann::json &survey)
Convert timer information to JSON.
Definition survey.cpp:348
static void SurveySettingsTable(nlohmann::json &survey, const SettingTable &table, void *object, bool skip_if_default)
Convert a settings table to JSON.
Definition survey.cpp:150
void SurveyGameSession(nlohmann::json &survey)
Convert game session information to JSON.
Definition survey.cpp:247
std::string SurveyMemoryToText(uint64_t memory)
Change the bytes of memory into a textual version rounded up to the biggest unit.
Definition survey.cpp:493
void SurveyGameScript(nlohmann::json &survey)
Convert game-script information to JSON.
Definition survey.cpp:391
void SurveyConfiguration(nlohmann::json &survey)
Convert generic game information to JSON.
Definition survey.cpp:261
void SurveyOpenTTD(nlohmann::json &survey)
Convert generic OpenTTD information to JSON.
Definition survey.cpp:215
void SurveyFont(nlohmann::json &survey)
Convert font information to JSON.
Definition survey.cpp:304
void SurveyCompanies(nlohmann::json &survey)
Convert company information to JSON.
Definition survey.cpp:317
static auto & GenericSettingTables()
List of all the generic setting tables.
Definition survey.cpp:123
void SurveyCompiler(nlohmann::json &survey)
Convert compiler information to JSON.
Definition survey.cpp:187
void SurveyLibraries(nlohmann::json &survey)
Convert compiled libraries information to JSON.
Definition survey.cpp:403
static const std::string _vehicle_type_to_string[]
Lookup table to convert a VehicleType to a string.
Definition survey.cpp:105
void SurveyGrfs(nlohmann::json &survey)
Convert GRF information to JSON.
Definition survey.cpp:364
Functions to survey the current game / system, for crashlog and network-survey.
Definition of the game-calendar-timer.
Definition of the game-economy-timer.
Definition of the tick-based game-timer.
VehicleType
Available vehicle types.
@ VEH_COMPANY_END
Last company-ownable type.
Base of all video drivers.
std::string FS2OTTD(std::wstring_view name)
Convert to OpenTTD's encoding from a wide string.
Definition win32.cpp:352