OpenTTD Source 20260218-master-g2123fca5ea
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 = GLAT_NONE;
37 this->current_action = nullptr;
38}
39
40Gamelog::~Gamelog()
41{
42}
43
48static std::string GetGamelogRevisionString()
49{
50 if (IsReleasedVersion()) {
51 return _openttd_revision;
52 }
53
54 /* Prefix character indication revision status */
55 assert(_openttd_revision_modified < 3);
56 return fmt::format("{}{}",
57 "gum"[_openttd_revision_modified], // g = "git", u = "unknown", m = "modified"
58 _openttd_revision_hash);
59}
60
67{
68 assert(this->action_type == GLAT_NONE); // do not allow starting new action without stopping the previous first
69 this->action_type = at;
70}
71
76{
77 assert(this->action_type != GLAT_NONE); // nobody should try to stop if there is no action in progress
78
79 bool print = this->current_action != nullptr;
80
81 this->current_action = nullptr;
82 this->action_type = GLAT_NONE;
83
84 if (print) this->PrintDebug(5);
85}
86
87void Gamelog::StopAnyAction()
88{
89 if (this->action_type != GLAT_NONE) this->StopAction();
90}
91
96{
97 assert(this->action_type == GLAT_NONE);
98 this->data->action.clear();
99 this->current_action = nullptr;
100}
101
109static void AddGrfInfo(std::back_insert_iterator<std::string> &output_iterator, uint32_t grfid, const MD5Hash *md5sum, const GRFConfig *gc)
110{
111 if (md5sum != nullptr) {
112 fmt::format_to(output_iterator, "GRF ID {:08X}, checksum {}", std::byteswap(grfid), FormatArrayAsHex(*md5sum));
113 } else {
114 fmt::format_to(output_iterator, "GRF ID {:08X}", std::byteswap(grfid));
115 }
116
117 if (gc != nullptr) {
118 fmt::format_to(output_iterator, ", filename: {} (md5sum matches)", gc->filename);
119 } else {
120 gc = FindGRFConfig(grfid, FGCM_ANY);
121 if (gc != nullptr) {
122 fmt::format_to(output_iterator, ", filename: {} (matches GRFID only)", gc->filename);
123 } else {
124 fmt::format_to(output_iterator, ", unknown GRF");
125 }
126 }
127}
128
129
131static const std::string_view la_text[] = {
132 "new game started",
133 "game loaded",
134 "GRF config changed",
135 "cheat was used",
136 "settings changed",
137 "GRF bug triggered",
138 "emergency savegame",
139};
140
141static_assert(lengthof(la_text) == GLAT_END);
142
147void Gamelog::Print(std::function<void(const std::string &)> proc)
148{
149 GrfIDMapping grf_names;
150
151 proc("---- gamelog start ----");
152
153 for (const LoggedAction &la : this->data->action) {
154 assert(la.at < GLAT_END);
155
156 proc(fmt::format("Tick {}: {}", la.tick, la_text[la.at]));
157
158 for (auto &lc : la.change) {
159 std::string message;
160 auto output_iterator = std::back_inserter(message);
161 lc->FormatTo(output_iterator, grf_names, la.at);
162
163 proc(message);
164 }
165 }
166
167 proc("---- gamelog end ----");
168}
169
170
171/* virtual */ void LoggedChangeMode::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
172{
173 /* Changing landscape, or going from scenario editor to game or back. */
174 fmt::format_to(output_iterator, "New game mode: {} landscape: {}", this->mode, this->landscape);
175}
176
177/* virtual */ void LoggedChangeRevision::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
178{
179 /* The game was loaded in a different version than before. */
180 fmt::format_to(output_iterator, "Revision text changed to {}, savegame version {}, ",
181 this->text, this->slver);
182
183 switch (this->modified) {
184 case 0: fmt::format_to(output_iterator, "not "); break;
185 case 1: fmt::format_to(output_iterator, "maybe "); break;
186 default: break;
187 }
188
189 fmt::format_to(output_iterator, "modified, _openttd_newgrf_version = 0x{:08x}", this->newgrf);
190}
191
192/* virtual */ void LoggedChangeOldVersion::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
193{
194 /* The game was loaded from before 0.7.0-beta1. */
195 fmt::format_to(output_iterator, "Conversion from ");
196 switch (this->type) {
197 default: NOT_REACHED();
198 case SGT_OTTD:
199 fmt::format_to(output_iterator, "OTTD savegame without gamelog: version {}, {}",
200 GB(this->version, 8, 16), GB(this->version, 0, 8));
201 break;
202
203 case SGT_TTO:
204 fmt::format_to(output_iterator, "TTO savegame");
205 break;
206
207 case SGT_TTD:
208 fmt::format_to(output_iterator, "TTD savegame");
209 break;
210
211 case SGT_TTDP1:
212 case SGT_TTDP2:
213 fmt::format_to(output_iterator, "TTDP savegame, {} format",
214 this->type == SGT_TTDP1 ? "old" : "new");
215 if (this->version != 0) {
216 fmt::format_to(output_iterator, ", TTDP version {}.{}.{}.{}",
217 GB(this->version, 24, 8), GB(this->version, 20, 4),
218 GB(this->version, 16, 4), GB(this->version, 0, 16));
219 }
220 break;
221 }
222}
223
224/* virtual */ void LoggedChangeSettingChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
225{
226 /* A setting with the SettingFlag::NoNetwork flag got changed; these settings usually affect NewGRFs, such as road side or wagon speed limits. */
227 fmt::format_to(output_iterator, "Setting changed: {} : {} -> {}", this->name, this->oldval, this->newval);
228}
229
230/* virtual */ void LoggedChangeGRFAdd::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
231{
232 /* 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. */
233 const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, &this->md5sum);
234 fmt::format_to(output_iterator, "Added NewGRF: ");
235 AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc);
236 auto gm = grf_names.find(this->grfid);
237 if (gm != grf_names.end() && !gm->second.was_missing) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was already added!");
238 grf_names[this->grfid] = gc;
239}
240
241/* virtual */ void LoggedChangeGRFRemoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type)
242{
243 /* A NewGRF got removed from the game, either manually or by it missing when loading the game. */
244 auto gm = grf_names.find(this->grfid);
245 if (action_type == GLAT_LOAD) {
246 fmt::format_to(output_iterator, "Missing NewGRF: ");
247 } else {
248 fmt::format_to(output_iterator, "Removed NewGRF: ");
249 }
250 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
251 if (gm == grf_names.end()) {
252 fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
253 } else {
254 if (action_type == GLAT_LOAD) {
255 /* Missing grfs on load are not removed from the configuration */
256 gm->second.was_missing = true;
257 } else {
258 grf_names.erase(gm);
259 }
260 }
261}
262
263/* virtual */ void LoggedChangeGRFChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
264{
265 /* Another version of the same NewGRF got loaded. */
266 const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, &this->md5sum);
267 fmt::format_to(output_iterator, "Compatible NewGRF loaded: ");
268 AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc);
269 if (grf_names.count(this->grfid) == 0) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
270 grf_names[this->grfid] = gc;
271}
272
273/* virtual */ void LoggedChangeGRFParameterChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
274{
275 /* A parameter of a NewGRF got changed after the game was started. */
276 auto gm = grf_names.find(this->grfid);
277 fmt::format_to(output_iterator, "GRF parameter changed: ");
278 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
279 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
280}
281
282/* virtual */ void LoggedChangeGRFMoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
283{
284 /* The order of NewGRFs got changed, which might cause some other NewGRFs to behave differently. */
285 auto gm = grf_names.find(this->grfid);
286 fmt::format_to(output_iterator, "GRF order changed: {:08X} moved {} places {}",
287 std::byteswap(this->grfid), abs(this->offset), this->offset >= 0 ? "down" : "up" );
288 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
289 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
290}
291
292/* virtual */ void LoggedChangeGRFBug::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
293{
294 /* A specific bug in a NewGRF, that could cause wide spread problems, has been noted during the execution of the game. */
295 auto gm = grf_names.find(this->grfid);
296 assert(this->bug == GRFBug::VehLength);
297
298 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);
299 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
300 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
301}
302
303/* virtual */ void LoggedChangeEmergencySave::FormatTo(std::back_insert_iterator<std::string> &, GrfIDMapping &, GamelogActionType)
304{
305 /* At one point the savegame was made during the handling of a game crash.
306 * The generic code already mentioned the emergency savegame, and there is no extra information to log. */
307}
308
311{
312 this->Print([](const std::string &s) {
314 });
315}
316
323void Gamelog::PrintDebug(int level)
324{
325 this->Print([level](const std::string &s) {
326 Debug(gamelog, level, "{}", s);
327 });
328}
329
330
335void Gamelog::Change(std::unique_ptr<LoggedChange> &&change)
336{
337 if (this->current_action == nullptr) {
338 if (this->action_type == GLAT_NONE) return;
339
340 this->current_action = &this->data->action.emplace_back();
341 this->current_action->at = this->action_type;
342 this->current_action->tick = TimerGameTick::counter;
343 }
344
345 this->current_action->change.push_back(std::move(change));
346}
347
348
353{
354 /* Terminate any active action */
355 if (this->action_type != GLAT_NONE) this->StopAction();
357 this->Change(std::make_unique<LoggedChangeEmergencySave>());
358 this->StopAction();
359}
360
366{
367 for (const LoggedAction &la : this->data->action) {
368 for (const auto &lc : la.change) {
369 if (lc->ct == GLCT_EMERGENCY) return true;
370 }
371 }
372
373 return false;
374}
375
380{
381 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD);
382
383 this->Change(std::make_unique<LoggedChangeRevision>(
384 GetGamelogRevisionString(), _openttd_newgrf_version, SAVEGAME_VERSION, _openttd_revision_modified));
385}
386
391{
392 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD || this->action_type == GLAT_CHEAT);
393
394 this->Change(std::make_unique<LoggedChangeMode>(_game_mode, _settings_game.game_creation.landscape));
395}
396
401{
402 assert(this->action_type == GLAT_LOAD);
403
404 this->Change(std::make_unique<LoggedChangeOldVersion>(_savegame_type,
406}
407
414void Gamelog::Setting(const std::string &name, int32_t oldval, int32_t newval)
415{
416 assert(this->action_type == GLAT_SETTING);
417
418 this->Change(std::make_unique<LoggedChangeSettingChanged>(name, oldval, newval));
419}
420
421
427{
428 const LoggedChangeRevision *rev = nullptr;
429
430 for (const LoggedAction &la : this->data->action) {
431 for (const auto &lc : la.change) {
432 if (lc->ct == GLCT_REVISION) rev = static_cast<const LoggedChangeRevision *>(lc.get());
433 }
434 }
435
436 if (rev == nullptr || rev->text != GetGamelogRevisionString() ||
437 rev->modified != _openttd_revision_modified ||
438 rev->newgrf != _openttd_newgrf_version) {
439 this->Revision();
440 }
441}
442
448{
449 const LoggedChangeMode *mode = nullptr;
450
451 for (const LoggedAction &la : this->data->action) {
452 for (const auto &lc : la.change) {
453 if (lc->ct == GLCT_MODE) mode = static_cast<const LoggedChangeMode *>(lc.get());
454 }
455 }
456
457 if (mode == nullptr || mode->mode != _game_mode || mode->landscape != _settings_game.game_creation.landscape) this->Mode();
458}
459
460
467void Gamelog::GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
468{
469 assert(this->action_type == GLAT_GRFBUG);
470
471 this->Change(std::make_unique<LoggedChangeGRFBug>(data, grfid, bug));
472}
473
483bool Gamelog::GRFBugReverse(uint32_t grfid, uint16_t internal_id)
484{
485 for (const LoggedAction &la : this->data->action) {
486 for (const auto &lc : la.change) {
487 if (lc->ct == GLCT_GRFBUG) {
488 LoggedChangeGRFBug *bug = static_cast<LoggedChangeGRFBug *>(lc.get());
489 if (bug->grfid == grfid && bug->bug == GRFBug::VehLength && bug->data == internal_id) {
490 return false;
491 }
492 }
493 }
494 }
495
497 this->GRFBug(grfid, GRFBug::VehLength, internal_id);
498 this->StopAction();
499
500 return true;
501}
502
503
509static inline bool IsLoggableGrfConfig(const GRFConfig &g)
510{
512}
513
518void Gamelog::GRFRemove(uint32_t grfid)
519{
520 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_GRF);
521
522 this->Change(std::make_unique<LoggedChangeGRFRemoved>(grfid));
523}
524
529void Gamelog::GRFAdd(const GRFConfig &newg)
530{
531 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_START || this->action_type == GLAT_GRF);
532
533 if (!IsLoggableGrfConfig(newg)) return;
534
535 this->Change(std::make_unique<LoggedChangeGRFAdd>(newg.ident));
536}
537
544{
545 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_GRF);
546
547 this->Change(std::make_unique<LoggedChangeGRFChanged>(newg));
548}
549
555void Gamelog::GRFMove(uint32_t grfid, int32_t offset)
556{
557 assert(this->action_type == GLAT_GRF);
558
559 this->Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
560}
561
567void Gamelog::GRFParameters(uint32_t grfid)
568{
569 assert(this->action_type == GLAT_GRF);
570
571 this->Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
572}
573
579void Gamelog::GRFAddList(const GRFConfigList &newg)
580{
581 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD);
582
583 for (const auto &c : newg) {
584 this->GRFAdd(*c);
585 }
586}
587
593static std::vector<const GRFConfig *> GenerateGRFList(const GRFConfigList &grfc)
594{
595 std::vector<const GRFConfig *> list;
596 for (const auto &g : grfc) {
597 if (IsLoggableGrfConfig(*g)) list.push_back(g.get());
598 }
599
600 return list;
601}
602
608void Gamelog::GRFUpdate(const GRFConfigList &oldc, const GRFConfigList &newc)
609{
610 std::vector<const GRFConfig *> ol = GenerateGRFList(oldc);
611 std::vector<const GRFConfig *> nl = GenerateGRFList(newc);
612
613 uint o = 0, n = 0;
614
615 while (o < ol.size() && n < nl.size()) {
616 const GRFConfig &og = *ol[o];
617 const GRFConfig &ng = *nl[n];
618
619 if (og.ident.grfid != ng.ident.grfid) {
620 uint oi, ni;
621 for (oi = 0; oi < ol.size(); oi++) {
622 if (ol[oi]->ident.grfid == nl[n]->ident.grfid) break;
623 }
624 if (oi < o) {
625 /* GRF was moved, this change has been logged already */
626 n++;
627 continue;
628 }
629 if (oi == ol.size()) {
630 /* GRF couldn't be found in the OLD list, GRF was ADDED */
631 this->GRFAdd(*nl[n++]);
632 continue;
633 }
634 for (ni = 0; ni < nl.size(); ni++) {
635 if (nl[ni]->ident.grfid == ol[o]->ident.grfid) break;
636 }
637 if (ni < n) {
638 /* GRF was moved, this change has been logged already */
639 o++;
640 continue;
641 }
642 if (ni == nl.size()) {
643 /* GRF couldn't be found in the NEW list, GRF was REMOVED */
644 this->GRFRemove(ol[o++]->ident.grfid);
645 continue;
646 }
647
648 /* o < oi < ol->n
649 * n < ni < nl->n */
650 assert(ni > n && ni < nl.size());
651 assert(oi > o && oi < ol.size());
652
653 ni -= n; // number of GRFs it was moved downwards
654 oi -= o; // number of GRFs it was moved upwards
655
656 if (ni >= oi) { // prefer the one that is moved further
657 /* GRF was moved down */
658 this->GRFMove(ol[o++]->ident.grfid, ni);
659 } else {
660 this->GRFMove(nl[n++]->ident.grfid, -(int)oi);
661 }
662 } else {
663 if (og.ident.md5sum != ng.ident.md5sum) {
664 /* md5sum changed, probably loading 'compatible' GRF */
665 this->GRFCompatible(nl[n]->ident);
666 }
667
668 if (og.param != ng.param) {
669 this->GRFParameters(ol[o]->ident.grfid);
670 }
671
672 o++;
673 n++;
674 }
675 }
676
677 while (o < ol.size()) this->GRFRemove(ol[o++]->ident.grfid); // remaining GRFs were removed ...
678 while (n < nl.size()) this->GRFAdd (*nl[n++]); // ... or added
679}
680
687void Gamelog::Info(uint32_t *last_ottd_rev, uint8_t *ever_modified, bool *removed_newgrfs)
688{
689 for (const LoggedAction &la : this->data->action) {
690 for (const auto &lc : la.change) {
691 switch (lc->ct) {
692 default: break;
693
694 case GLCT_REVISION: {
695 const LoggedChangeRevision *rev = static_cast<const LoggedChangeRevision *>(lc.get());
696 *last_ottd_rev = rev->newgrf;
697 *ever_modified = std::max(*ever_modified, rev->modified);
698 break;
699 }
700
701 case GLCT_GRFREM:
702 *removed_newgrfs = true;
703 break;
704 }
705 }
706 }
707}
708
715{
716 const LoggedAction &la = this->data->action.back();
717 if (la.at != GLAT_LOAD) return c.ident;
718
719 for (const auto &lc : la.change) {
720 if (lc->ct != GLCT_GRFCOMPAT) continue;
721
722 const LoggedChangeGRFChanged &grf = *static_cast<const LoggedChangeGRFChanged *>(lc.get());
723 if (grf.grfid == c.ident.grfid) return grf;
724 }
725
726 return c.ident;
727}
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:426
const GRFIdentifier & GetOverriddenIdentifier(const GRFConfig &c)
Try to find the overridden GRF identifier of the given GRF.
Definition gamelog.cpp:714
void Mode()
Logs a change in game mode (scenario editor or game).
Definition gamelog.cpp:390
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:687
void PrintDebug(int level)
Prints gamelog to debug output.
Definition gamelog.cpp:323
void PrintConsole()
Print the gamelog data to the console.
Definition gamelog.cpp:310
void GRFParameters(uint32_t grfid)
Logs change in GRF parameters.
Definition gamelog.cpp:567
void Revision()
Logs a change in game revision.
Definition gamelog.cpp:379
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:66
void Reset()
Resets and frees all memory allocated - used before loading or starting a new game.
Definition gamelog.cpp:95
void GRFRemove(uint32_t grfid)
Logs removal of a GRF.
Definition gamelog.cpp:518
void GRFAddList(const GRFConfigList &newg)
Logs adding of list of GRFs.
Definition gamelog.cpp:579
void GRFCompatible(const GRFIdentifier &newg)
Logs loading compatible GRF (the same ID, but different MD5 hash).
Definition gamelog.cpp:543
void Oldver()
Logs loading from savegame without gamelog.
Definition gamelog.cpp:400
void Emergency()
Logs a emergency savegame.
Definition gamelog.cpp:352
bool GRFBugReverse(uint32_t grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition gamelog.cpp:483
void TestMode()
Finds last stored game mode or landscape.
Definition gamelog.cpp:447
void StopAction()
Stops logging of any changes.
Definition gamelog.cpp:75
void Setting(const std::string &name, int32_t oldval, int32_t newval)
Logs change in game settings.
Definition gamelog.cpp:414
void Print(std::function< void(const std::string &)> proc)
Prints active gamelog.
Definition gamelog.cpp:147
void GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
Logs triggered GRF bug.
Definition gamelog.cpp:467
void GRFAdd(const GRFConfig &newg)
Logs adding of a GRF.
Definition gamelog.cpp:529
void GRFUpdate(const GRFConfigList &oldg, const GRFConfigList &newg)
Compares two NewGRF lists and logs any change.
Definition gamelog.cpp:608
void Change(std::unique_ptr< LoggedChange > &&change)
Allocates a new LoggedAction if needed, and add the change when action is active.
Definition gamelog.cpp:335
bool TestEmergency()
Finds out if current game is a loaded emergency savegame.
Definition gamelog.cpp:365
void GRFMove(uint32_t grfid, int32_t offset)
Logs changing GRF order.
Definition gamelog.cpp:555
static TickCounter counter
Monotonic counter, in ticks, since start of game.
void IConsolePrint(TextColour 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
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:48
Gamelog _gamelog
Gamelog instance.
Definition gamelog.cpp:31
static void AddGrfInfo(std::back_insert_iterator< std::string > &output_iterator, uint32_t grfid, const MD5Hash *md5sum, const GRFConfig *gc)
Adds the GRF ID, checksum and filename if found to the output iterator.
Definition gamelog.cpp:109
static bool IsLoggableGrfConfig(const GRFConfig &g)
Decides if GRF should be logged.
Definition gamelog.cpp:509
SavegameType _savegame_type
type of savegame we are loading
Definition saveload.cpp:77
static const std::string_view la_text[]
Text messages for various logged actions.
Definition gamelog.cpp:131
static std::vector< const GRFConfig * > GenerateGRFList(const GRFConfigList &grfc)
Generates GRFList.
Definition gamelog.cpp:593
const SaveLoadVersion SAVEGAME_VERSION
current savegame version
@ GLCT_MODE
Scenario editor x Game, different landscape.
Definition gamelog.h:30
@ GLCT_GRFCOMPAT
Loading compatible GRF.
Definition gamelog.h:36
@ GLCT_EMERGENCY
Emergency savegame.
Definition gamelog.h:40
@ GLCT_GRFREM
Added GRF.
Definition gamelog.h:35
@ GLCT_GRFBUG
GRF bug triggered.
Definition gamelog.h:39
@ GLCT_REVISION
Changed game revision string.
Definition gamelog.h:31
GamelogActionType
The actions we log.
Definition gamelog.h:16
@ GLAT_GRFBUG
GRF bug was triggered.
Definition gamelog.h:22
@ GLAT_START
Game created.
Definition gamelog.h:17
@ GLAT_NONE
No logging active; in savegames, end of list.
Definition gamelog.h:25
@ GLAT_GRF
GRF changed.
Definition gamelog.h:19
@ GLAT_END
So we know how many GLATs are there.
Definition gamelog.h:24
@ GLAT_LOAD
Game loaded.
Definition gamelog.h:18
@ GLAT_CHEAT
Cheat was used.
Definition gamelog.h:20
@ GLAT_EMERGENCY
Emergency savegame.
Definition gamelog.h:23
@ GLAT_SETTING
Setting changed.
Definition gamelog.h:21
Declaration shared among gamelog.cpp and saveload/gamelog_sl.cpp.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
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.
@ 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.
@ FGCM_ANY
Use first found.
@ FGCM_EXACT
Only find Grfs matching md5sum.
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:440
@ SGT_TTD
TTD savegame (can be detected incorrectly).
Definition saveload.h:441
@ SGT_OTTD
OTTD savegame.
Definition saveload.h:444
@ SGT_TTDP2
TTDP savegame in new format (data at SE border).
Definition saveload.h:443
@ SGT_TTO
TTO savegame.
Definition saveload.h:445
@ SGT_TTDP1
TTDP savegame ( -//- ) (data at NW border).
Definition saveload.h:442
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.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
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.
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).
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:303
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:230
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:292
uint64_t data
additional data
uint32_t grfid
ID of problematic 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:263
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:282
uint32_t grfid
ID of moved GRF.
int32_t offset
offset, positive = move down
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:273
uint32_t grfid
ID of GRF with changed parameters.
uint32_t 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:241
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:171
uint8_t 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:192
uint32_t type
type of savegame,
uint32_t version
major and minor version OR ttdp 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:177
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:224
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.