OpenTTD Source 20260711-master-g3fb3006dff
gamelog.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#include "saveload/saveload.h"
12#include "string_func.h"
13#include "settings_type.h"
14#include "gamelog_internal.h"
15#include "console_func.h"
16#include "debug.h"
19#include "rev.h"
20
21#include "safeguards.h"
22
24
26
27extern uint32_t _ttdp_version;
29extern uint8_t _sl_minor_version;
30
32
33Gamelog::Gamelog()
34{
35 this->data = std::make_unique<GamelogInternalData>();
36 this->action_type = GamelogActionType::None;
37 this->current_action = nullptr;
38}
39
44
49static std::string GetGamelogRevisionString()
50{
51 if (IsReleasedVersion()) {
52 return _openttd_revision;
53 }
54
55 /* Prefix character indication revision status */
56 assert(_openttd_revision_modified < 3);
57 return fmt::format("{}{}",
58 "gum"[_openttd_revision_modified], // g = "git", u = "unknown", m = "modified"
59 _openttd_revision_hash);
60}
61
68{
69 assert(this->action_type == GamelogActionType::None); // do not allow starting new action without stopping the previous first
70 this->action_type = at;
71}
72
77{
78 assert(this->action_type != GamelogActionType::None); // nobody should try to stop if there is no action in progress
79
80 bool print = this->current_action != nullptr;
81
82 this->current_action = nullptr;
83 this->action_type = GamelogActionType::None;
84
85 if (print) this->PrintDebug(5);
86}
87
88void Gamelog::StopAnyAction()
89{
90 if (this->action_type != GamelogActionType::None) this->StopAction();
91}
92
97{
98 assert(this->action_type == GamelogActionType::None);
99 this->data->action.clear();
100 this->current_action = nullptr;
101}
102
110static void AddGrfInfo(std::back_insert_iterator<std::string> &output_iterator, GrfID grfid, const MD5Hash *md5sum, const GRFConfig *gc)
111{
112 if (md5sum != nullptr) {
113 fmt::format_to(output_iterator, "GRF ID {:08X}, checksum {}", std::byteswap(grfid), FormatArrayAsHex(*md5sum));
114 } else {
115 fmt::format_to(output_iterator, "GRF ID {:08X}", std::byteswap(grfid));
116 }
117
118 if (gc != nullptr) {
119 fmt::format_to(output_iterator, ", filename: {} (md5sum matches)", gc->filename);
120 } else {
122 if (gc != nullptr) {
123 fmt::format_to(output_iterator, ", filename: {} (matches GRFID only)", gc->filename);
124 } else {
125 fmt::format_to(output_iterator, ", unknown GRF");
126 }
127 }
128}
129
130
133 "new game started",
134 "game loaded",
135 "GRF config changed",
136 "cheat was used",
137 "settings changed",
138 "GRF bug triggered",
139 "emergency savegame",
140};
141
146void Gamelog::Print(std::function<void(const std::string &)> proc)
147{
148 GrfIDMapping grf_names;
149
150 proc("---- gamelog start ----");
151
152 for (const LoggedAction &la : this->data->action) {
153 assert(la.at < GamelogActionType::End);
154
155 proc(fmt::format("Tick {}: {}", la.tick, la_text[la.at]));
156
157 for (auto &lc : la.change) {
158 std::string message;
159 auto output_iterator = std::back_inserter(message);
160 lc->FormatTo(output_iterator, grf_names, la.at);
161
162 proc(message);
163 }
164 }
165
166 proc("---- gamelog end ----");
167}
168
169
170/* virtual */ void LoggedChangeMode::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
171{
172 /* Changing landscape, or going from scenario editor to game or back. */
173 fmt::format_to(output_iterator, "New game mode: {} landscape: {}", this->mode, this->landscape);
174}
175
176/* virtual */ void LoggedChangeRevision::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
177{
178 /* The game was loaded in a different version than before. */
179 fmt::format_to(output_iterator, "Revision text changed to {}, savegame version {}, ",
180 this->text, this->slver);
181
182 switch (this->modified) {
183 case 0: fmt::format_to(output_iterator, "not "); break;
184 case 1: fmt::format_to(output_iterator, "maybe "); break;
185 default: break;
186 }
187
188 fmt::format_to(output_iterator, "modified, _openttd_newgrf_version = 0x{:08x}", this->newgrf);
189}
190
191/* virtual */ void LoggedChangeOldVersion::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
192{
193 /* The game was loaded from before 0.7.0-beta1. */
194 fmt::format_to(output_iterator, "Conversion from ");
195 switch (this->type) {
196 default: NOT_REACHED();
198 fmt::format_to(output_iterator, "OTTD savegame without gamelog: version {}, {}",
199 GB(this->version, 8, 16), GB(this->version, 0, 8));
200 break;
201
203 fmt::format_to(output_iterator, "TTO savegame");
204 break;
205
207 fmt::format_to(output_iterator, "TTD savegame");
208 break;
209
212 fmt::format_to(output_iterator, "TTDP savegame, {} format",
213 this->type == SavegameType::TTDP1 ? "old" : "new");
214 if (this->version != 0) {
215 fmt::format_to(output_iterator, ", TTDP version {}.{}.{}.{}",
216 GB(this->version, 24, 8), GB(this->version, 20, 4),
217 GB(this->version, 16, 4), GB(this->version, 0, 16));
218 }
219 break;
220 }
221}
222
223/* virtual */ void LoggedChangeSettingChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
224{
225 /* A setting with the SettingFlag::NoNetwork flag got changed; these settings usually affect NewGRFs, such as road side or wagon speed limits. */
226 fmt::format_to(output_iterator, "Setting changed: {} : {} -> {}", this->name, this->oldval, this->newval);
227}
228
229/* virtual */ void LoggedChangeGRFAdd::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
230{
231 /* A NewGRF got added to the game, either at the start of the game (never an issue), or later on when it could be an issue. */
232 const GRFConfig *gc = FindGRFConfig(this->grfid, FindGRFConfigMode::Exact, &this->md5sum);
233 fmt::format_to(output_iterator, "Added NewGRF: ");
234 AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc);
235 auto gm = grf_names.find(this->grfid);
236 if (gm != grf_names.end() && !gm->second.was_missing) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was already added!");
237 grf_names[this->grfid] = gc;
238}
239
240/* virtual */ void LoggedChangeGRFRemoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type)
241{
242 /* A NewGRF got removed from the game, either manually or by it missing when loading the game. */
243 auto gm = grf_names.find(this->grfid);
244 if (action_type == GamelogActionType::Load) {
245 fmt::format_to(output_iterator, "Missing NewGRF: ");
246 } else {
247 fmt::format_to(output_iterator, "Removed NewGRF: ");
248 }
249 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
250 if (gm == grf_names.end()) {
251 fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
252 } else {
253 if (action_type == GamelogActionType::Load) {
254 /* Missing grfs on load are not removed from the configuration */
255 gm->second.was_missing = true;
256 } else {
257 grf_names.erase(gm);
258 }
259 }
260}
261
262/* virtual */ void LoggedChangeGRFChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
263{
264 /* Another version of the same NewGRF got loaded. */
265 const GRFConfig *gc = FindGRFConfig(this->grfid, FindGRFConfigMode::Exact, &this->md5sum);
266 fmt::format_to(output_iterator, "Compatible NewGRF loaded: ");
267 AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc);
268 if (grf_names.count(this->grfid) == 0) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
269 grf_names[this->grfid] = gc;
270}
271
272/* virtual */ void LoggedChangeGRFParameterChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
273{
274 /* A parameter of a NewGRF got changed after the game was started. */
275 auto gm = grf_names.find(this->grfid);
276 fmt::format_to(output_iterator, "GRF parameter changed: ");
277 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
278 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
279}
280
281/* virtual */ void LoggedChangeGRFMoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
282{
283 /* The order of NewGRFs got changed, which might cause some other NewGRFs to behave differently. */
284 auto gm = grf_names.find(this->grfid);
285 fmt::format_to(output_iterator, "GRF order changed: {:08X} moved {} places {}",
286 std::byteswap(this->grfid), abs(this->offset), this->offset >= 0 ? "down" : "up" );
287 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
288 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
289}
290
291/* virtual */ void LoggedChangeGRFBug::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
292{
293 /* A specific bug in a NewGRF, that could cause wide spread problems, has been noted during the execution of the game. */
294 auto gm = grf_names.find(this->grfid);
295 assert(this->bug == GRFBug::VehLength);
296
297 fmt::format_to(output_iterator, "Rail vehicle changes length outside a depot: GRF ID {:08X}, internal ID 0x{:X}", std::byteswap(this->grfid), this->data);
298 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
299 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
300}
301
302/* virtual */ void LoggedChangeEmergencySave::FormatTo(std::back_insert_iterator<std::string> &, GrfIDMapping &, GamelogActionType)
303{
304 /* At one point the savegame was made during the handling of a game crash.
305 * The generic code already mentioned the emergency savegame, and there is no extra information to log. */
306}
307
310{
311 this->Print([](const std::string &s) {
313 });
314}
315
322void Gamelog::PrintDebug(int level)
323{
324 this->Print([level](const std::string &s) {
325 Debug(gamelog, level, "{}", s);
326 });
327}
328
329
334void Gamelog::Change(std::unique_ptr<LoggedChange> &&change)
335{
336 if (this->current_action == nullptr) {
337 if (this->action_type == GamelogActionType::None) return;
338
339 this->current_action = &this->data->action.emplace_back();
340 this->current_action->at = this->action_type;
341 this->current_action->tick = TimerGameTick::counter;
342 }
343
344 this->current_action->change.push_back(std::move(change));
345}
346
347
352{
353 /* Terminate any active action */
354 if (this->action_type != GamelogActionType::None) this->StopAction();
356 this->Change(std::make_unique<LoggedChangeEmergencySave>());
357 this->StopAction();
358}
359
365{
366 for (const LoggedAction &la : this->data->action) {
367 for (const auto &lc : la.change) {
368 if (lc->ct == GamelogChangeType::Emergency) return true;
369 }
370 }
371
372 return false;
373}
374
379{
380 assert(this->action_type == GamelogActionType::Start || this->action_type == GamelogActionType::Load);
381
382 this->Change(std::make_unique<LoggedChangeRevision>(
383 GetGamelogRevisionString(), _openttd_newgrf_version, to_underlying(SAVEGAME_VERSION), _openttd_revision_modified));
384}
385
390{
391 assert(this->action_type == GamelogActionType::Start || this->action_type == GamelogActionType::Load || this->action_type == GamelogActionType::Cheat);
392
393 this->Change(std::make_unique<LoggedChangeMode>(_game_mode, _settings_game.game_creation.landscape));
394}
395
400{
401 assert(this->action_type == GamelogActionType::Load);
402
403 this->Change(std::make_unique<LoggedChangeOldVersion>(_savegame_type,
404 (_savegame_type == SavegameType::OTTD ? (static_cast<uint32_t>(_sl_version) << 8 | _sl_minor_version) : _ttdp_version)));
405}
406
413void Gamelog::Setting(const std::string &name, int32_t oldval, int32_t newval)
414{
415 assert(this->action_type == GamelogActionType::Setting);
416
417 this->Change(std::make_unique<LoggedChangeSettingChanged>(name, oldval, newval));
418}
419
420
426{
427 const LoggedChangeRevision *rev = nullptr;
428
429 for (const LoggedAction &la : this->data->action) {
430 for (const auto &lc : la.change) {
431 if (lc->ct == GamelogChangeType::Revision) rev = static_cast<const LoggedChangeRevision *>(lc.get());
432 }
433 }
434
435 if (rev == nullptr || rev->text != GetGamelogRevisionString() ||
436 rev->modified != _openttd_revision_modified ||
437 rev->newgrf != _openttd_newgrf_version) {
438 this->Revision();
439 }
440}
441
447{
448 const LoggedChangeMode *mode = nullptr;
449
450 for (const LoggedAction &la : this->data->action) {
451 for (const auto &lc : la.change) {
452 if (lc->ct == GamelogChangeType::Mode) mode = static_cast<const LoggedChangeMode *>(lc.get());
453 }
454 }
455
456 if (mode == nullptr || mode->mode != _game_mode || mode->landscape != _settings_game.game_creation.landscape) this->Mode();
457}
458
459
466void Gamelog::GRFBug(GrfID grfid, ::GRFBug bug, uint64_t data)
467{
468 assert(this->action_type == GamelogActionType::GRFBug);
469
470 this->Change(std::make_unique<LoggedChangeGRFBug>(data, grfid, bug));
471}
472
482bool Gamelog::GRFBugReverse(GrfID grfid, uint16_t internal_id)
483{
484 for (const LoggedAction &la : this->data->action) {
485 for (const auto &lc : la.change) {
486 if (lc->ct == GamelogChangeType::GRFBug) {
487 LoggedChangeGRFBug *bug = static_cast<LoggedChangeGRFBug *>(lc.get());
488 if (bug->grfid == grfid && bug->bug == GRFBug::VehLength && bug->data == internal_id) {
489 return false;
490 }
491 }
492 }
493 }
494
496 this->GRFBug(grfid, GRFBug::VehLength, internal_id);
497 this->StopAction();
498
499 return true;
500}
501
502
508static inline bool IsLoggableGrfConfig(const GRFConfig &g)
509{
511}
512
518{
519 assert(this->action_type == GamelogActionType::Load || this->action_type == GamelogActionType::GRF);
520
521 this->Change(std::make_unique<LoggedChangeGRFRemoved>(grfid));
522}
523
528void Gamelog::GRFAdd(const GRFConfig &newg)
529{
530 assert(this->action_type == GamelogActionType::Load || this->action_type == GamelogActionType::Start || this->action_type == GamelogActionType::GRF);
531
532 if (!IsLoggableGrfConfig(newg)) return;
533
534 this->Change(std::make_unique<LoggedChangeGRFAdd>(newg.ident));
535}
536
543{
544 assert(this->action_type == GamelogActionType::Load || this->action_type == GamelogActionType::GRF);
545
546 this->Change(std::make_unique<LoggedChangeGRFChanged>(newg));
547}
548
554void Gamelog::GRFMove(GrfID grfid, int32_t offset)
555{
556 assert(this->action_type == GamelogActionType::GRF);
557
558 this->Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
559}
560
567{
568 assert(this->action_type == GamelogActionType::GRF);
569
570 this->Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
571}
572
578void Gamelog::GRFAddList(const GRFConfigList &newg)
579{
580 assert(this->action_type == GamelogActionType::Start || this->action_type == GamelogActionType::Load);
581
582 for (const auto &c : newg) {
583 this->GRFAdd(*c);
584 }
585}
586
592static std::vector<const GRFConfig *> GenerateGRFList(const GRFConfigList &grfc)
593{
594 std::vector<const GRFConfig *> list;
595 for (const auto &g : grfc) {
596 if (IsLoggableGrfConfig(*g)) list.push_back(g.get());
597 }
598
599 return list;
600}
601
607void Gamelog::GRFUpdate(const GRFConfigList &oldc, const GRFConfigList &newc)
608{
609 std::vector<const GRFConfig *> ol = GenerateGRFList(oldc);
610 std::vector<const GRFConfig *> nl = GenerateGRFList(newc);
611
612 uint o = 0, n = 0;
613
614 while (o < ol.size() && n < nl.size()) {
615 const GRFConfig &og = *ol[o];
616 const GRFConfig &ng = *nl[n];
617
618 if (og.ident.grfid != ng.ident.grfid) {
619 uint oi, ni;
620 for (oi = 0; oi < ol.size(); oi++) {
621 if (ol[oi]->ident.grfid == nl[n]->ident.grfid) break;
622 }
623 if (oi < o) {
624 /* GRF was moved, this change has been logged already */
625 n++;
626 continue;
627 }
628 if (oi == ol.size()) {
629 /* GRF couldn't be found in the OLD list, GRF was ADDED */
630 this->GRFAdd(*nl[n++]);
631 continue;
632 }
633 for (ni = 0; ni < nl.size(); ni++) {
634 if (nl[ni]->ident.grfid == ol[o]->ident.grfid) break;
635 }
636 if (ni < n) {
637 /* GRF was moved, this change has been logged already */
638 o++;
639 continue;
640 }
641 if (ni == nl.size()) {
642 /* GRF couldn't be found in the NEW list, GRF was REMOVED */
643 this->GRFRemove(ol[o++]->ident.grfid);
644 continue;
645 }
646
647 /* o < oi < ol->n
648 * n < ni < nl->n */
649 assert(ni > n && ni < nl.size());
650 assert(oi > o && oi < ol.size());
651
652 ni -= n; // number of GRFs it was moved downwards
653 oi -= o; // number of GRFs it was moved upwards
654
655 if (ni >= oi) { // prefer the one that is moved further
656 /* GRF was moved down */
657 this->GRFMove(ol[o++]->ident.grfid, ni);
658 } else {
659 this->GRFMove(nl[n++]->ident.grfid, -(int)oi);
660 }
661 } else {
662 if (og.ident.md5sum != ng.ident.md5sum) {
663 /* md5sum changed, probably loading 'compatible' GRF */
664 this->GRFCompatible(nl[n]->ident);
665 }
666
667 if (og.param != ng.param) {
668 this->GRFParameters(ol[o]->ident.grfid);
669 }
670
671 o++;
672 n++;
673 }
674 }
675
676 while (o < ol.size()) this->GRFRemove(ol[o++]->ident.grfid); // remaining GRFs were removed ...
677 while (n < nl.size()) this->GRFAdd (*nl[n++]); // ... or added
678}
679
686void Gamelog::Info(uint32_t *last_ottd_rev, uint8_t *ever_modified, bool *removed_newgrfs)
687{
688 for (const LoggedAction &la : this->data->action) {
689 for (const auto &lc : la.change) {
690 switch (lc->ct) {
691 default: break;
692
694 const LoggedChangeRevision *rev = static_cast<const LoggedChangeRevision *>(lc.get());
695 *last_ottd_rev = rev->newgrf;
696 *ever_modified = std::max(*ever_modified, rev->modified);
697 break;
698 }
699
701 *removed_newgrfs = true;
702 break;
703 }
704 }
705 }
706}
707
714{
715 const LoggedAction &la = this->data->action.back();
716 if (la.at != GamelogActionType::Load) return c.ident;
717
718 for (const auto &lc : la.change) {
719 if (lc->ct != GamelogChangeType::GRFCompat) continue;
720
721 const LoggedChangeGRFChanged &grf = *static_cast<const LoggedChangeGRFChanged *>(lc.get());
722 if (grf.grfid == c.ident.grfid) return grf;
723 }
724
725 return c.ident;
726}
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
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.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
void TestRevision()
Finds out if current revision is different than last revision stored in the savegame.
Definition gamelog.cpp:425
const GRFIdentifier & GetOverriddenIdentifier(const GRFConfig &c)
Try to find the overridden GRF identifier of the given GRF.
Definition gamelog.cpp:713
bool GRFBugReverse(GrfID grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition gamelog.cpp:482
void Mode()
Logs a change in game mode (scenario editor or game).
Definition gamelog.cpp:389
void Info(uint32_t *last_ottd_rev, uint8_t *ever_modified, bool *removed_newgrfs)
Get some basic information from the given gamelog.
Definition gamelog.cpp:686
void PrintDebug(int level)
Prints gamelog to debug output.
Definition gamelog.cpp:322
void PrintConsole()
Print the gamelog data to the console.
Definition gamelog.cpp:309
void GRFParameters(GrfID grfid)
Logs change in GRF parameters.
Definition gamelog.cpp:566
void Revision()
Logs a change in game revision.
Definition gamelog.cpp:378
void StartAction(GamelogActionType at)
Stores information about new action, but doesn't allocate it Action is allocated only when there is a...
Definition gamelog.cpp:67
void Reset()
Resets and frees all memory allocated - used before loading or starting a new game.
Definition gamelog.cpp:96
void GRFRemove(GrfID grfid)
Logs removal of a GRF.
Definition gamelog.cpp:517
void GRFMove(GrfID grfid, int32_t offset)
Logs changing GRF order.
Definition gamelog.cpp:554
void GRFAddList(const GRFConfigList &newg)
Logs adding of list of GRFs.
Definition gamelog.cpp:578
~Gamelog()
Needs to be manually defined due to incomplete definition of GamelogInternalData in the header.
Definition gamelog.cpp:41
void GRFCompatible(const GRFIdentifier &newg)
Logs loading compatible GRF (the same ID, but different MD5 hash).
Definition gamelog.cpp:542
void Oldver()
Logs loading from savegame without gamelog.
Definition gamelog.cpp:399
void Emergency()
Logs a emergency savegame.
Definition gamelog.cpp:351
void TestMode()
Finds last stored game mode or landscape.
Definition gamelog.cpp:446
void StopAction()
Stops logging of any changes.
Definition gamelog.cpp:76
void GRFBug(GrfID grfid, ::GRFBug bug, uint64_t data)
Logs triggered GRF bug.
Definition gamelog.cpp:466
void Setting(const std::string &name, int32_t oldval, int32_t newval)
Logs change in game settings.
Definition gamelog.cpp:413
void Print(std::function< void(const std::string &)> proc)
Prints active gamelog.
Definition gamelog.cpp:146
void GRFAdd(const GRFConfig &newg)
Logs adding of a GRF.
Definition gamelog.cpp:528
void GRFUpdate(const GRFConfigList &oldg, const GRFConfigList &newg)
Compares two NewGRF lists and logs any change.
Definition gamelog.cpp:607
void Change(std::unique_ptr< LoggedChange > &&change)
Allocates a new LoggedAction if needed, and add the change when action is active.
Definition gamelog.cpp:334
bool TestEmergency()
Finds out if current game is a loaded emergency savegame.
Definition gamelog.cpp:364
static TickCounter counter
Monotonic counter, in ticks, since start of game.
void IConsolePrint(ExtendedTextColour 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:90
Console functions used outside of the console code.
static const TextColour CC_WARNING
Colour for warning lines.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
uint32_t _ttdp_version
version of TTDP savegame (if applicable)
Definition saveload.cpp:80
SaveLoadVersion _sl_version
the major savegame version identifier
Definition saveload.cpp:81
uint8_t _sl_minor_version
the minor savegame version, DO NOT USE!
Definition saveload.cpp:82
static std::string GetGamelogRevisionString()
Return the revision string for the current client version, for use in gamelog.
Definition gamelog.cpp:49
Gamelog _gamelog
Gamelog instance.
Definition gamelog.cpp:31
static bool IsLoggableGrfConfig(const GRFConfig &g)
Decides if GRF should be logged.
Definition gamelog.cpp:508
static constexpr EnumIndexArray< std::string_view, GamelogActionType, GamelogActionType::End > la_text
Text messages for various logged actions.
Definition gamelog.cpp:132
SavegameType _savegame_type
type of savegame we are loading
Definition saveload.cpp:77
static std::vector< const GRFConfig * > GenerateGRFList(const GRFConfigList &grfc)
Generates GRFList.
Definition gamelog.cpp:592
const SaveLoadVersion SAVEGAME_VERSION
current savegame version
static void AddGrfInfo(std::back_insert_iterator< std::string > &output_iterator, GrfID grfid, const MD5Hash *md5sum, const GRFConfig *gc)
Adds the GRF ID, checksum and filename if found to the output iterator.
Definition gamelog.cpp:110
@ GRFCompat
Loading compatible GRF.
Definition gamelog.h:37
@ Revision
Changed game revision string.
Definition gamelog.h:32
@ GRFRem
Added GRF.
Definition gamelog.h:36
@ Mode
Scenario editor x Game, different landscape.
Definition gamelog.h:31
@ Emergency
Emergency savegame.
Definition gamelog.h:41
@ GRFBug
GRF bug triggered.
Definition gamelog.h:40
GamelogActionType
The actions we log.
Definition gamelog.h:17
@ Setting
Setting changed.
Definition gamelog.h:22
@ Cheat
Cheat was used.
Definition gamelog.h:21
@ None
No logging active; in savegames, end of list.
Definition gamelog.h:26
@ End
End marker.
Definition gamelog.h:25
@ GRF
GRF changed.
Definition gamelog.h:20
@ Emergency
Emergency savegame.
Definition gamelog.h:24
@ Start
Game created.
Definition gamelog.h:18
@ GRFBug
GRF bug was triggered.
Definition gamelog.h:23
@ Load
Game loaded.
Definition gamelog.h:19
Declaration shared among gamelog.cpp and saveload/gamelog_sl.cpp.
std::map< GrfID, GRFPresence > GrfIDMapping
A mapping from GrfID to the GRFPresence.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
const GRFConfig * FindGRFConfig(GrfID grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
@ NotFound
GRF file was not found in the local cache.
@ Static
GRF file is used statically (can be used in any MP game).
GRFBug
Encountered GRF bugs.
@ VehLength
Length of rail vehicle changes when not inside a depot.
@ Exact
Only find Grfs matching md5sum.
@ Any
Use first found.
uint32_t GrfID
The unique identifier of a NewGRF.
Definition newgrf_type.h:15
Declaration of OTTD revision dependent variables.
A number of safeguards to prevent using unsafe methods.
Functions/types related to saving and loading games.
SavegameType
Types of save games.
Definition saveload.h:443
@ TTDP1
TTDP savegame ( -//- ) (data at NW border).
Definition saveload.h:445
@ TTO
TTO savegame.
Definition saveload.h:448
@ TTD
TTD savegame (can be detected incorrectly).
Definition saveload.h:444
@ TTDP2
TTDP savegame in new format (data at SE border).
Definition saveload.h:446
@ OTTD
OTTD savegame.
Definition saveload.h:447
SaveLoadVersion
SaveLoad versions Previous savegame versions, the trunk revision where they were introduced and the r...
Definition saveload.h:30
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
Types related to global configuration settings.
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
Functions related to low-level strings.
Information about GRF, used in the game and (part of it) in savegames.
std::vector< uint32_t > param
GRF parameters.
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.
GrfID 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).
Contains information about one logged action that caused at least one logged change.
uint64_t tick
Tick when it happened.
std::vector< std::unique_ptr< LoggedChange > > change
Logged changes in this action.
GamelogActionType at
Type of action.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:302
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:229
A log entry for a NewGRF bug.
GRFBug bug
type of bug,
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:291
GrfID grfid
ID of problematic GRF.
uint64_t data
additional data
A log entry for a NewGRF that was changed.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:262
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:281
int32_t offset
offset, positive = move down
GrfID grfid
ID of moved GRF.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:272
GrfID grfid
ID of GRF with changed parameters.
GrfID grfid
ID of removed GRF.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:240
Log element for the change of the game mode and landscape.
LandscapeType landscape
landscape (temperate, arctic, ...)
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:170
GameMode mode
new game mode - Editor x Game
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:191
uint32_t type
type of savegame,
uint32_t version
major and minor version OR ttdp version
A log entry for a change in OpenTTD version.
std::string text
revision string, _openttd_revision
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:176
uint16_t slver
_sl_version
uint32_t newgrf
_openttd_newgrf_version
uint8_t modified
_openttd_revision_modified
std::string name
name of the setting
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Definition gamelog.cpp:223
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.