diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 52b2bc4afc..62f1bdde70 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2250,6 +2250,19 @@ DEF_CONSOLE_CMD(ConDumpCommandLog) return true; } +DEF_CONSOLE_CMD(ConDumpSpecialEventsLog) +{ + if (argc == 0) { + IConsoleHelp("Dump log of special events."); + return true; + } + + char buffer[32768]; + DumpSpecialEventsLog(buffer, lastof(buffer)); + PrintLineByLine(buffer); + return true; +} + DEF_CONSOLE_CMD(ConDumpDesyncMsgLog) { if (argc == 0) { @@ -3470,6 +3483,7 @@ void IConsoleStdLibRegister() IConsole::CmdRegister("getfulldate", ConGetFullDate, nullptr, true); IConsole::CmdRegister("dump_command_log", ConDumpCommandLog, nullptr, true); + IConsole::CmdRegister("dump_special_events_log", ConDumpSpecialEventsLog, nullptr, true); IConsole::CmdRegister("dump_desync_msgs", ConDumpDesyncMsgLog, nullptr, true); IConsole::CmdRegister("dump_inflation", ConDumpInflation, nullptr, true); IConsole::CmdRegister("dump_cpdp_stats", ConDumpCpdpStats, nullptr, true); diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 63212d29a4..3664c0d165 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -411,6 +411,8 @@ char *CrashLog::LogCommandLog(char *buffer, const char *last) const { buffer = DumpCommandLog(buffer, last); buffer += seprintf(buffer, last, "\n"); + buffer = DumpSpecialEventsLog(buffer, last); + buffer += seprintf(buffer, last, "\n"); return buffer; } diff --git a/src/economy.cpp b/src/economy.cpp index 501db7006d..dcdc7e5932 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -590,6 +590,12 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) cur_company.Restore(); + if (new_owner != INVALID_OWNER) { + AppendSpecialEventsLogEntry(stdstr_fmt("Company merge: old: %u, new %u", old_owner, new_owner)); + } else { + AppendSpecialEventsLogEntry(stdstr_fmt("Company deletion: old: %u", old_owner)); + } + RegisterGameEvents(new_owner != INVALID_OWNER ? GEF_COMPANY_MERGE : GEF_COMPANY_DELETE); MarkWholeScreenDirty(); diff --git a/src/event_logs.cpp b/src/event_logs.cpp index 10bab41261..2b4bde0417 100644 --- a/src/event_logs.cpp +++ b/src/event_logs.cpp @@ -10,6 +10,10 @@ #include "stdafx.h" #include "event_logs.h" #include "string_func.h" +#include "date_func.h" +#include "company_func.h" +#include +#include #include "safeguards.h" @@ -35,3 +39,66 @@ char *DumpGameEventFlags(GameEventFlags events, char *b, const char *last) dump('v', GEF_VIRT_TRAIN); return b; } + +struct SpecialEventLogEntry { + std::string msg; + Date date; + DateFract date_fract; + uint8 tick_skip_counter; + CompanyID current_company; + CompanyID local_company; + + SpecialEventLogEntry() { } + + SpecialEventLogEntry(std::string msg) + : msg(std::move(msg)), date(_date), date_fract(_date_fract), tick_skip_counter(_tick_skip_counter), + current_company(_current_company), local_company(_local_company) { } +}; + +struct SpecialEventLog { + std::array log; + unsigned int count = 0; + unsigned int next = 0; + + void Reset() + { + this->count = 0; + this->next = 0; + } +}; + +static SpecialEventLog _special_event_log; + +void AppendSpecialEventsLogEntry(std::string message) +{ + _special_event_log.log[_special_event_log.next] = SpecialEventLogEntry(std::move(message)); + _special_event_log.next = (_special_event_log.next + 1) % _special_event_log.log.size(); + _special_event_log.count++; +} + +char *DumpSpecialEventsLog(char *buffer, const char *last) +{ + const unsigned int count = std::min(_special_event_log.count, 64); + buffer += seprintf(buffer, last, "Special Events Log:\n Showing most recent %u of %u events\n", count, _special_event_log.count); + + unsigned int log_index = _special_event_log.next; + for (unsigned int i = 0 ; i < count; i++) { + if (log_index > 0) { + log_index--; + } else { + log_index = (uint)_special_event_log.log.size() - 1; + } + const SpecialEventLogEntry &entry = _special_event_log.log[log_index]; + + YearMonthDay ymd; + ConvertDateToYMD(entry.date, &ymd); + buffer += seprintf(buffer, last, " %3u | %4i-%02i-%02i, %2i, %3i | cc: %3u, lc: %3u | %s\n", + i, ymd.year, ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, (uint) entry.current_company, (uint) entry.local_company, entry.msg.c_str()); + } + return buffer; +} + +void ClearSpecialEventsLog() +{ + _special_event_log.Reset(); +} diff --git a/src/event_logs.h b/src/event_logs.h index 2cbf6b2dff..bdf3bdc8c4 100644 --- a/src/event_logs.h +++ b/src/event_logs.h @@ -39,4 +39,8 @@ char *DumpGameEventFlags(GameEventFlags events, char *b, const char *last); extern time_t _game_load_time; +void AppendSpecialEventsLogEntry(std::string message); +char *DumpSpecialEventsLog(char *buffer, const char *last); +void ClearSpecialEventsLog(); + #endif /* EVENT_LOGS_H */ diff --git a/src/misc.cpp b/src/misc.cpp index 2b4120a14c..69559daa45 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -79,6 +79,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin ViewportMapClearTunnelCache(); ClearCommandLog(); + ClearSpecialEventsLog(); ClearDesyncMsgLog(); _pause_mode = PM_UNPAUSED; diff --git a/src/openttd.cpp b/src/openttd.cpp index 6e96cfbae7..a094d5b6d7 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -457,6 +457,7 @@ static void ShutdownGame() ClearVehicleTickCaches(); InvalidateTemplateReplacementImages(); ClearCommandLog(); + ClearSpecialEventsLog(); ClearDesyncMsgLog(); _loaded_local_company = COMPANY_SPECTATOR; diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 65d0c57c4f..6bd6da48cc 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -4031,6 +4031,7 @@ bool AfterLoadGame() void ReloadNewGRFData() { RegisterGameEvents(GEF_RELOAD_NEWGRF); + AppendSpecialEventsLogEntry("NewGRF reload"); RailTypeLabel rail_type_label_map[RAILTYPE_END]; for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {