OpenTTD Source 20260208-master-g43af8e94d0
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
47static std::string GetGamelogRevisionString()
48{
49 if (IsReleasedVersion()) {
50 return _openttd_revision;
51 }
52
53 /* Prefix character indication revision status */
54 assert(_openttd_revision_modified < 3);
55 return fmt::format("{}{}",
56 "gum"[_openttd_revision_modified], // g = "git", u = "unknown", m = "modified"
57 _openttd_revision_hash);
58}
59
66{
67 assert(this->action_type == GLAT_NONE); // do not allow starting new action without stopping the previous first
68 this->action_type = at;
69}
70
75{
76 assert(this->action_type != GLAT_NONE); // nobody should try to stop if there is no action in progress
77
78 bool print = this->current_action != nullptr;
79
80 this->current_action = nullptr;
81 this->action_type = GLAT_NONE;
82
83 if (print) this->PrintDebug(5);
84}
85
86void Gamelog::StopAnyAction()
87{
88 if (this->action_type != GLAT_NONE) this->StopAction();
89}
90
95{
96 assert(this->action_type == GLAT_NONE);
97 this->data->action.clear();
98 this->current_action = nullptr;
99}
100
108static void AddGrfInfo(std::back_insert_iterator<std::string> &output_iterator, uint32_t grfid, const MD5Hash *md5sum, const GRFConfig *gc)
109{
110 if (md5sum != nullptr) {
111 fmt::format_to(output_iterator, "GRF ID {:08X}, checksum {}", std::byteswap(grfid), FormatArrayAsHex(*md5sum));
112 } else {
113 fmt::format_to(output_iterator, "GRF ID {:08X}", std::byteswap(grfid));
114 }
115
116 if (gc != nullptr) {
117 fmt::format_to(output_iterator, ", filename: {} (md5sum matches)", gc->filename);
118 } else {
119 gc = FindGRFConfig(grfid, FGCM_ANY);
120 if (gc != nullptr) {
121 fmt::format_to(output_iterator, ", filename: {} (matches GRFID only)", gc->filename);
122 } else {
123 fmt::format_to(output_iterator, ", unknown GRF");
124 }
125 }
126}
127
128
130static const std::string_view la_text[] = {
131 "new game started",
132 "game loaded",
133 "GRF config changed",
134 "cheat was used",
135 "settings changed",
136 "GRF bug triggered",
137 "emergency savegame",
138};
139
140static_assert(lengthof(la_text) == GLAT_END);
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 < GLAT_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();
197 case SGT_OTTD:
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
202 case SGT_TTO:
203 fmt::format_to(output_iterator, "TTO savegame");
204 break;
205
206 case SGT_TTD:
207 fmt::format_to(output_iterator, "TTD savegame");
208 break;
209
210 case SGT_TTDP1:
211 case SGT_TTDP2:
212 fmt::format_to(output_iterator, "TTDP savegame, {} format",
213 this->type == SGT_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, FGCM_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 == GLAT_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 == GLAT_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, FGCM_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 == GLAT_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 != GLAT_NONE) this->StopAction();
356 this->Change(std::make_unique<LoggedChangeEmergencySave>());
357 this->StopAction();
358}
359
364{
365 for (const LoggedAction &la : this->data->action) {
366 for (const auto &lc : la.change) {
367 if (lc->ct == GLCT_EMERGENCY) return true;
368 }
369 }
370
371 return false;
372}
373
378{
379 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD);
380
381 this->Change(std::make_unique<LoggedChangeRevision>(
382 GetGamelogRevisionString(), _openttd_newgrf_version, SAVEGAME_VERSION, _openttd_revision_modified));
383}
384
389{
390 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD || this->action_type == GLAT_CHEAT);
391
392 this->Change(std::make_unique<LoggedChangeMode>(_game_mode, _settings_game.game_creation.landscape));
393}
394
399{
400 assert(this->action_type == GLAT_LOAD);
401
402 this->Change(std::make_unique<LoggedChangeOldVersion>(_savegame_type,
404}
405
412void Gamelog::Setting(const std::string &name, int32_t oldval, int32_t newval)
413{
414 assert(this->action_type == GLAT_SETTING);
415
416 this->Change(std::make_unique<LoggedChangeSettingChanged>(name, oldval, newval));
417}
418
419
425{
426 const LoggedChangeRevision *rev = nullptr;
427
428 for (const LoggedAction &la : this->data->action) {
429 for (const auto &lc : la.change) {
430 if (lc->ct == GLCT_REVISION) rev = static_cast<const LoggedChangeRevision *>(lc.get());
431 }
432 }
433
434 if (rev == nullptr || rev->text != GetGamelogRevisionString() ||
435 rev->modified != _openttd_revision_modified ||
436 rev->newgrf != _openttd_newgrf_version) {
437 this->Revision();
438 }
439}
440
446{
447 const LoggedChangeMode *mode = nullptr;
448
449 for (const LoggedAction &la : this->data->action) {
450 for (const auto &lc : la.change) {
451 if (lc->ct == GLCT_MODE) mode = static_cast<const LoggedChangeMode *>(lc.get());
452 }
453 }
454
455 if (mode == nullptr || mode->mode != _game_mode || mode->landscape != _settings_game.game_creation.landscape) this->Mode();
456}
457
458
465void Gamelog::GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
466{
467 assert(this->action_type == GLAT_GRFBUG);
468
469 this->Change(std::make_unique<LoggedChangeGRFBug>(data, grfid, bug));
470}
471
481bool Gamelog::GRFBugReverse(uint32_t grfid, uint16_t internal_id)
482{
483 for (const LoggedAction &la : this->data->action) {
484 for (const auto &lc : la.change) {
485 if (lc->ct == GLCT_GRFBUG) {
486 LoggedChangeGRFBug *bug = static_cast<LoggedChangeGRFBug *>(lc.get());
487 if (bug->grfid == grfid && bug->bug == GRFBug::VehLength && bug->data == internal_id) {
488 return false;
489 }
490 }
491 }
492 }
493
495 this->GRFBug(grfid, GRFBug::VehLength, internal_id);
496 this->StopAction();
497
498 return true;
499}
500
501
507static inline bool IsLoggableGrfConfig(const GRFConfig &g)
508{
510}
511
516void Gamelog::GRFRemove(uint32_t grfid)
517{
518 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_GRF);
519
520 this->Change(std::make_unique<LoggedChangeGRFRemoved>(grfid));
521}
522
527void Gamelog::GRFAdd(const GRFConfig &newg)
528{
529 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_START || this->action_type == GLAT_GRF);
530
531 if (!IsLoggableGrfConfig(newg)) return;
532
533 this->Change(std::make_unique<LoggedChangeGRFAdd>(newg.ident));
534}
535
542{
543 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_GRF);
544
545 this->Change(std::make_unique<LoggedChangeGRFChanged>(newg));
546}
547
553void Gamelog::GRFMove(uint32_t grfid, int32_t offset)
554{
555 assert(this->action_type == GLAT_GRF);
556
557 this->Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
558}
559
565void Gamelog::GRFParameters(uint32_t grfid)
566{
567 assert(this->action_type == GLAT_GRF);
568
569 this->Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
570}
571
577void Gamelog::GRFAddList(const GRFConfigList &newg)
578{
579 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD);
580
581 for (const auto &c : newg) {
582 this->GRFAdd(*c);
583 }
584}
585
590static std::vector<const GRFConfig *> GenerateGRFList(const GRFConfigList &grfc)
591{
592 std::vector<const GRFConfig *> list;
593 for (const auto &g : grfc) {
594 if (IsLoggableGrfConfig(*g)) list.push_back(g.get());
595 }
596
597 return list;
598}
599
605void Gamelog::GRFUpdate(const GRFConfigList &oldc, const GRFConfigList &newc)
606{
607 std::vector<const GRFConfig *> ol = GenerateGRFList(oldc);
608 std::vector<const GRFConfig *> nl = GenerateGRFList(newc);
609
610 uint o = 0, n = 0;
611
612 while (o < ol.size() && n < nl.size()) {
613 const GRFConfig &og = *ol[o];
614 const GRFConfig &ng = *nl[n];
615
616 if (og.ident.grfid != ng.ident.grfid) {
617 uint oi, ni;
618 for (oi = 0; oi < ol.size(); oi++) {
619 if (ol[oi]->ident.grfid == nl[n]->ident.grfid) break;
620 }
621 if (oi < o) {
622 /* GRF was moved, this change has been logged already */
623 n++;
624 continue;
625 }
626 if (oi == ol.size()) {
627 /* GRF couldn't be found in the OLD list, GRF was ADDED */
628 this->GRFAdd(*nl[n++]);
629 continue;
630 }
631 for (ni = 0; ni < nl.size(); ni++) {
632 if (nl[ni]->ident.grfid == ol[o]->ident.grfid) break;
633 }
634 if (ni < n) {
635 /* GRF was moved, this change has been logged already */
636 o++;
637 continue;
638 }
639 if (ni == nl.size()) {
640 /* GRF couldn't be found in the NEW list, GRF was REMOVED */
641 this->GRFRemove(ol[o++]->ident.grfid);
642 continue;
643 }
644
645 /* o < oi < ol->n
646 * n < ni < nl->n */
647 assert(ni > n && ni < nl.size());
648 assert(oi > o && oi < ol.size());
649
650 ni -= n; // number of GRFs it was moved downwards
651 oi -= o; // number of GRFs it was moved upwards
652
653 if (ni >= oi) { // prefer the one that is moved further
654 /* GRF was moved down */
655 this->GRFMove(ol[o++]->ident.grfid, ni);
656 } else {
657 this->GRFMove(nl[n++]->ident.grfid, -(int)oi);
658 }
659 } else {
660 if (og.ident.md5sum != ng.ident.md5sum) {
661 /* md5sum changed, probably loading 'compatible' GRF */
662 this->GRFCompatible(nl[n]->ident);
663 }
664
665 if (og.param != ng.param) {
666 this->GRFParameters(ol[o]->ident.grfid);
667 }
668
669 o++;
670 n++;
671 }
672 }
673
674 while (o < ol.size()) this->GRFRemove(ol[o++]->ident.grfid); // remaining GRFs were removed ...
675 while (n < nl.size()) this->GRFAdd (*nl[n++]); // ... or added
676}
677
684void Gamelog::Info(uint32_t *last_ottd_rev, uint8_t *ever_modified, bool *removed_newgrfs)
685{
686 for (const LoggedAction &la : this->data->action) {
687 for (const auto &lc : la.change) {
688 switch (lc->ct) {
689 default: break;
690
691 case GLCT_REVISION: {
692 const LoggedChangeRevision *rev = static_cast<const LoggedChangeRevision *>(lc.get());
693 *last_ottd_rev = rev->newgrf;
694 *ever_modified = std::max(*ever_modified, rev->modified);
695 break;
696 }
697
698 case GLCT_GRFREM:
699 *removed_newgrfs = true;
700 break;
701 }
702 }
703 }
704}
705
712{
713 const LoggedAction &la = this->data->action.back();
714 if (la.at != GLAT_LOAD) return c.ident;
715
716 for (const auto &lc : la.change) {
717 if (lc->ct != GLCT_GRFCOMPAT) continue;
718
719 const LoggedChangeGRFChanged &grf = *static_cast<const LoggedChangeGRFChanged *>(lc.get());
720 if (grf.grfid == c.ident.grfid) return grf;
721 }
722
723 return c.ident;
724}
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:424
const GRFIdentifier & GetOverriddenIdentifier(const GRFConfig &c)
Try to find the overridden GRF identifier of the given GRF.
Definition gamelog.cpp:711
void Mode()
Logs a change in game mode (scenario editor or game).
Definition gamelog.cpp:388
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:684
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(uint32_t grfid)
Logs change in GRF parameters.
Definition gamelog.cpp:565
void Revision()
Logs a change in game revision.
Definition gamelog.cpp:377
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:65
void Reset()
Resets and frees all memory allocated - used before loading or starting a new game.
Definition gamelog.cpp:94
void GRFRemove(uint32_t grfid)
Logs removal of a GRF.
Definition gamelog.cpp:516
void GRFAddList(const GRFConfigList &newg)
Logs adding of list of GRFs.
Definition gamelog.cpp:577
void GRFCompatible(const GRFIdentifier &newg)
Logs loading compatible GRF (the same ID, but different MD5 hash).
Definition gamelog.cpp:541
void Oldver()
Logs loading from savegame without gamelog.
Definition gamelog.cpp:398
void Emergency()
Logs a emergency savegame.
Definition gamelog.cpp:351
bool GRFBugReverse(uint32_t grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition gamelog.cpp:481
void TestMode()
Finds last stored game mode or landscape.
Definition gamelog.cpp:445
void StopAction()
Stops logging of any changes.
Definition gamelog.cpp:74
void Setting(const std::string &name, int32_t oldval, int32_t newval)
Logs change in game settings.
Definition gamelog.cpp:412
void Print(std::function< void(const std::string &)> proc)
Prints active gamelog.
Definition gamelog.cpp:146
void GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
Logs triggered GRF bug.
Definition gamelog.cpp:465
void GRFAdd(const GRFConfig &newg)
Logs adding of a GRF.
Definition gamelog.cpp:527
void GRFUpdate(const GRFConfigList &oldg, const GRFConfigList &newg)
Compares two NewGRF lists and logs any change.
Definition gamelog.cpp:605
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:363
void GRFMove(uint32_t grfid, int32_t offset)
Logs changing GRF order.
Definition gamelog.cpp:553
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:47
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:108
static bool IsLoggableGrfConfig(const GRFConfig &g)
Decides if GRF should be logged.
Definition gamelog.cpp:507
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:130
static std::vector< const GRFConfig * > GenerateGRFList(const GRFConfigList &grfc)
Generates GRFList.
Definition gamelog.cpp:590
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: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
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
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: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
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:272
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:240
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
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:191
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: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.