26 #include "3rdparty/fmt/chrono.h"
27 #include "3rdparty/fmt/std.h"
43 json = nlohmann::json::array();
56 json = nlohmann::json::array();
59 for (
const auto &news :
GetNews()) {
61 json.push_back(fmt::format(
"({}-{:02}-{:02}) StringID: {}, Type: {}, Ref1: {}, {}, Ref2: {}, {}",
62 ymd.year, ymd.month + 1, ymd.day, news.string_id, news.type,
63 news.reftype1, news.ref1, news.reftype2, news.ref2));
76 static std::string crashname;
78 if (crashname.empty()) {
79 crashname = fmt::format(
"crash{:%Y%m%d%H%M%S}", fmt::gmtime(time(
nullptr)));
81 return fmt::format(
"{}{}{}", with_dir ?
_personal_dir : std::string{}, crashname, ext);
92 this->survey[
"date"] = fmt::format(
"{:%Y-%m-%d %H:%M:%S} (UTC)", fmt::gmtime(time(
nullptr)));
103 this->survey[
"stacktrace"] =
"crashed while gathering information";
107 this->survey[
"session"] =
"crashed while gathering information";
111 auto &info = this->survey[
"info"];
112 if (!this->
TryExecute(
"os", [&info]() { SurveyOS(info[
"os"]);
return true; })) {
113 info[
"os"] =
"crashed while gathering information";
116 info[
"openttd"] =
"crashed while gathering information";
119 info[
"configuration"] =
"crashed while gathering information";
122 info[
"font"] =
"crashed while gathering information";
125 info[
"compiler"] =
"crashed while gathering information";
128 info[
"libraries"] =
"crashed while gathering information";
131 info[
"plugins"] =
"crashed while gathering information";
136 auto &game = this->survey[
"game"];
141 game[
"libraries"] =
"crashed while gathering information";
144 game[
"companies"] =
"crashed while gathering information";
147 game[
"settings"] =
"crashed while gathering information";
150 game[
"grfs"] =
"crashed while gathering information";
153 game[
"game_script"] =
"crashed while gathering information";
156 game[
"gamelog"] =
"crashed while gathering information";
159 game[
"news"] =
"crashed while gathering information";
164 void CrashLog::PrintCrashLog()
const
166 fmt::print(
" OpenTTD version:\n");
167 fmt::print(
" Version: {}\n", this->survey[
"info"][
"openttd"][
"version"][
"revision"].get<std::string>());
168 fmt::print(
" Hash: {}\n", this->survey[
"info"][
"openttd"][
"version"][
"hash"].get<std::string>());
169 fmt::print(
" NewGRF ver: {}\n", this->survey[
"info"][
"openttd"][
"version"][
"newgrf"].get<std::string>());
170 fmt::print(
" Content ver: {}\n", this->survey[
"info"][
"openttd"][
"version"][
"content"].get<std::string>());
173 fmt::print(
" Crash:\n");
174 fmt::print(
" Reason: {}\n", this->survey[
"crash"][
"reason"].get<std::string>());
177 fmt::print(
" Stacktrace:\n");
178 for (
const auto &line : this->survey[
"stacktrace"]) {
179 fmt::print(
" {}\n", line.get<std::string>());
194 if (!file.has_value())
return false;
196 std::string survey_json = this->survey.dump(4);
198 size_t len = survey_json.size();
199 size_t written = fwrite(survey_json.data(), 1, len, *file);
201 return len == written;
212 fmt::print(
"No method to create a crash.dmp available.\n");
247 if (_screen.width < 1 || _screen.height < 1 || _screen.dst_ptr ==
nullptr)
return false;
260 if (_game_mode == GM_NORMAL) {
273 static bool crashlogged =
false;
274 if (crashlogged)
return;
277 fmt::print(
"Crash encountered, generating crash log...\n");
279 fmt::print(
"Crash log generated.\n\n");
281 fmt::print(
"Crash in summary:\n");
282 this->
TryExecute(
"crashlog", [
this]() { this->PrintCrashLog();
return true; });
284 fmt::print(
"Writing crash log to disk...\n");
287 fmt::print(
"Crash log written to {}. Please add this file to any bug reports.\n\n", this->crashlog_filename);
289 fmt::print(
"Writing crash log failed. Please attach the output above to any bug reports.\n\n");
290 this->crashlog_filename =
"(failed to write crash log)";
293 fmt::print(
"Writing crash dump to disk...\n");
296 fmt::print(
"Crash dump written to {}. Please add this file to any bug reports.\n\n", this->crashdump_filename);
298 fmt::print(
"Writing crash dump failed.\n\n");
299 this->crashdump_filename =
"(failed to write crash dump)";
302 fmt::print(
"Writing crash savegame...\n");
305 fmt::print(
"Crash savegame written to {}. Please add this file and the last (auto)save to any bug reports.\n\n", this->savegame_filename);
307 fmt::print(
"Writing crash savegame failed. Please attach the last (auto)save to any bug reports.\n\n");
308 this->savegame_filename =
"(failed to write crash savegame)";
311 fmt::print(
"Writing crash screenshot...\n");
314 fmt::print(
"Crash screenshot written to {}. Please add this file to any bug reports.\n\n", this->screenshot_filename);
316 fmt::print(
"Writing crash screenshot failed.\n\n");
317 this->screenshot_filename =
"(failed to write crash screenshot)";
void MakeCrashLog()
Makes the crash log, writes it to a file and then subsequently tries to make a crash dump and crash s...
bool WriteCrashLog()
Write the crash log to a file.
virtual void SurveyStacktrace(nlohmann::json &survey) const =0
Convert stacktrace to JSON.
std::string CreateFileName(const char *ext, bool with_dir=true) const
Create a timestamped filename.
static std::string message
Error message coming from #FatalError(format, ...).
void SendSurvey() const
Send the survey result, noting it was a crash.
virtual bool TryExecute(std::string_view section_name, std::function< bool()> &&func)=0
Execute the func() and return its value.
virtual bool WriteCrashDump()
Write the (crash) dump to a file.
bool WriteSavegame()
Write the (crash) savegame to a file.
bool WriteScreenshot()
Write the (crash) screenshot to a file.
void FillCrashLog()
Fill the crash log buffer with all data of a crash log.
static void SetErrorMessage(const std::string &message)
Sets a message for the error message handler.
virtual void SurveyCrash(nlohmann::json &survey) const =0
Convert system crash reason to JSON.
static void AfterCrashLogCleanup()
Try to close the sound/video stuff so it doesn't keep lingering around incorrect video states or so,...
virtual void Stop()=0
Stop this driver.
void Emergency()
Logs a emergency savegame.
void Print(std::function< void(const std::string &)> proc)
Prints active gamelog.
static MusicDriver * GetInstance()
Get the currently active instance of the music driver.
void Transmit(Reason reason, bool blocking=false)
Transmit the survey.
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 VideoDriver * GetInstance()
Get the currently active instance of the video driver.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
static void SurveyRecentNews(nlohmann::json &json)
Writes up to 32 recent news messages to the buffer, with the most recent first.
constexpr uint8_t CRASHLOG_SURVEY_VERSION
The version of the schema of the JSON information.
static void SurveyGamelog(nlohmann::json &json)
Writes the gamelog data to the buffer.
Functions to be called to log a crash.
std::string _personal_dir
custom directory for personal settings, saves, newgrf, etc.
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.
Functions for Standard In/Out file operations.
Types for Standard In/Out file operations.
@ SLO_SAVE
File is being saved.
@ DFT_GAME_FILE
Save game or scenario file.
@ NO_DIRECTORY
A path without any base directory.
Gamelog _gamelog
Gamelog instance.
Functions to be called to log fundamental changes to the game.
Functions related to maps.
Base for all music playback.
Part of the network protocol handling opt-in survey.
const NewsContainer & GetNews()
Get read-only reference to all news items.
GUI functions related to the news.
A number of safeguards to prevent using unsafe methods.
SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded)
Main Save or Load function where the high-level saveload functions are handled.
Functions/types related to saving and loading games.
@ SL_OK
completed successfully
bool MakeScreenshot(ScreenshotType t, std::string name, uint32_t width, uint32_t height)
Schedule making a screenshot.
std::string _full_screenshot_path
Pathname of the screenshot file.
Functions to make screenshots.
@ SC_CRASHLOG
Raw screenshot from blitter buffer.
Base for all sound drivers.
Definition of base types and functions in a cross-platform compatible way.
static bool IsInitialized()
Check whether the map has been initialized, as to not try to save the map during crashlog when the ma...
void SurveySettings(nlohmann::json &survey, bool skip_if_default)
Convert settings to JSON.
void SurveyPlugins(nlohmann::json &survey)
Convert plugin information to JSON.
void SurveyTimers(nlohmann::json &survey)
Convert timer information to JSON.
void SurveyGameSession(nlohmann::json &survey)
Convert game session information to JSON.
void SurveyGameScript(nlohmann::json &survey)
Convert game-script information to JSON.
void SurveyConfiguration(nlohmann::json &survey)
Convert generic game information to JSON.
void SurveyOpenTTD(nlohmann::json &survey)
Convert generic OpenTTD information to JSON.
void SurveyFont(nlohmann::json &survey)
Convert font information to JSON.
void SurveyCompanies(nlohmann::json &survey)
Convert company information to JSON.
void SurveyCompiler(nlohmann::json &survey)
Convert compiler information to JSON.
void SurveyLibraries(nlohmann::json &survey)
Convert compiled libraries information to JSON.
void SurveyGrfs(nlohmann::json &survey)
Convert GRF information to JSON.
Functions to survey the current game / system, for crashlog and network-survey.
Base of all video drivers.