OpenTTD Source 20260311-master-g511d3794ce
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
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 == GLAT_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 != GLAT_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 = GLAT_NONE;
84
85 if (print) this->PrintDebug(5);
86}
87
88void Gamelog::StopAnyAction()
89{
90 if (this->action_type != GLAT_NONE) this->StopAction();
91}
92
97{
98 assert(this->action_type == GLAT_NONE);
99 this->data->action.clear();
100 this->current_action = nullptr;
101}
102
110static void AddGrfInfo(std::back_insert_iterator<std::string> &output_iterator, uint32_t 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 {
121 gc = FindGRFConfig(grfid, FGCM_ANY);
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
132static const std::string_view la_text[] = {
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
142static_assert(lengthof(la_text) == GLAT_END);
143
148void Gamelog::Print(std::function<void(const std::string &)> proc)
149{
150 GrfIDMapping grf_names;
151
152 proc("---- gamelog start ----");
153
154 for (const LoggedAction &la : this->data->action) {
155 assert(la.at < GLAT_END);
156
157 proc(fmt::format("Tick {}: {}", la.tick, la_text[la.at]));
158
159 for (auto &lc : la.change) {
160 std::string message;
161 auto output_iterator = std::back_inserter(message);
162 lc->FormatTo(output_iterator, grf_names, la.at);
163
164 proc(message);
165 }
166 }
167
168 proc("---- gamelog end ----");
169}
170
171
172/* virtual */ void LoggedChangeMode::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
173{
174 /* Changing landscape, or going from scenario editor to game or back. */
175 fmt::format_to(output_iterator, "New game mode: {} landscape: {}", this->mode, this->landscape);
176}
177
178/* virtual */ void LoggedChangeRevision::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
179{
180 /* The game was loaded in a different version than before. */
181 fmt::format_to(output_iterator, "Revision text changed to {}, savegame version {}, ",
182 this->text, this->slver);
183
184 switch (this->modified) {
185 case 0: fmt::format_to(output_iterator, "not "); break;
186 case 1: fmt::format_to(output_iterator, "maybe "); break;
187 default: break;
188 }
189
190 fmt::format_to(output_iterator, "modified, _openttd_newgrf_version = 0x{:08x}", this->newgrf);
191}
192
193/* virtual */ void LoggedChangeOldVersion::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
194{
195 /* The game was loaded from before 0.7.0-beta1. */
196 fmt::format_to(output_iterator, "Conversion from ");
197 switch (this->type) {
198 default: NOT_REACHED();
199 case SGT_OTTD:
200 fmt::format_to(output_iterator, "OTTD savegame without gamelog: version {}, {}",
201 GB(this->version, 8, 16), GB(this->version, 0, 8));
202 break;
203
204 case SGT_TTO:
205 fmt::format_to(output_iterator, "TTO savegame");
206 break;
207
208 case SGT_TTD:
209 fmt::format_to(output_iterator, "TTD savegame");
210 break;
211
212 case SGT_TTDP1:
213 case SGT_TTDP2:
214 fmt::format_to(output_iterator, "TTDP savegame, {} format",
215 this->type == SGT_TTDP1 ? "old" : "new");
216 if (this->version != 0) {
217 fmt::format_to(output_iterator, ", TTDP version {}.{}.{}.{}",
218 GB(this->version, 24, 8), GB(this->version, 20, 4),
219 GB(this->version, 16, 4), GB(this->version, 0, 16));
220 }
221 break;
222 }
223}
224
225/* virtual */ void LoggedChangeSettingChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &, GamelogActionType)
226{
227 /* A setting with the SettingFlag::NoNetwork flag got changed; these settings usually affect NewGRFs, such as road side or wagon speed limits. */
228 fmt::format_to(output_iterator, "Setting changed: {} : {} -> {}", this->name, this->oldval, this->newval);
229}
230
231/* virtual */ void LoggedChangeGRFAdd::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
232{
233 /* 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. */
234 const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, &this->md5sum);
235 fmt::format_to(output_iterator, "Added NewGRF: ");
236 AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc);
237 auto gm = grf_names.find(this->grfid);
238 if (gm != grf_names.end() && !gm->second.was_missing) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was already added!");
239 grf_names[this->grfid] = gc;
240}
241
242/* virtual */ void LoggedChangeGRFRemoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type)
243{
244 /* A NewGRF got removed from the game, either manually or by it missing when loading the game. */
245 auto gm = grf_names.find(this->grfid);
246 if (action_type == GLAT_LOAD) {
247 fmt::format_to(output_iterator, "Missing NewGRF: ");
248 } else {
249 fmt::format_to(output_iterator, "Removed NewGRF: ");
250 }
251 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
252 if (gm == grf_names.end()) {
253 fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
254 } else {
255 if (action_type == GLAT_LOAD) {
256 /* Missing grfs on load are not removed from the configuration */
257 gm->second.was_missing = true;
258 } else {
259 grf_names.erase(gm);
260 }
261 }
262}
263
264/* virtual */ void LoggedChangeGRFChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
265{
266 /* Another version of the same NewGRF got loaded. */
267 const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, &this->md5sum);
268 fmt::format_to(output_iterator, "Compatible NewGRF loaded: ");
269 AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc);
270 if (grf_names.count(this->grfid) == 0) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
271 grf_names[this->grfid] = gc;
272}
273
274/* virtual */ void LoggedChangeGRFParameterChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
275{
276 /* A parameter of a NewGRF got changed after the game was started. */
277 auto gm = grf_names.find(this->grfid);
278 fmt::format_to(output_iterator, "GRF parameter changed: ");
279 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
280 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
281}
282
283/* virtual */ void LoggedChangeGRFMoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
284{
285 /* The order of NewGRFs got changed, which might cause some other NewGRFs to behave differently. */
286 auto gm = grf_names.find(this->grfid);
287 fmt::format_to(output_iterator, "GRF order changed: {:08X} moved {} places {}",
288 std::byteswap(this->grfid), abs(this->offset), this->offset >= 0 ? "down" : "up" );
289 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
290 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
291}
292
293/* virtual */ void LoggedChangeGRFBug::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names, GamelogActionType)
294{
295 /* A specific bug in a NewGRF, that could cause wide spread problems, has been noted during the execution of the game. */
296 auto gm = grf_names.find(this->grfid);
297 assert(this->bug == GRFBug::VehLength);
298
299 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);
300 AddGrfInfo(output_iterator, this->grfid, nullptr, gm != grf_names.end() ? gm->second.gc : nullptr);
301 if (gm == grf_names.end()) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!");
302}
303
304/* virtual */ void LoggedChangeEmergencySave::FormatTo(std::back_insert_iterator<std::string> &, GrfIDMapping &, GamelogActionType)
305{
306 /* At one point the savegame was made during the handling of a game crash.
307 * The generic code already mentioned the emergency savegame, and there is no extra information to log. */
308}
309
312{
313 this->Print([](const std::string &s) {
315 });
316}
317
324void Gamelog::PrintDebug(int level)
325{
326 this->Print([level](const std::string &s) {
327 Debug(gamelog, level, "{}", s);
328 });
329}
330
331
336void Gamelog::Change(std::unique_ptr<LoggedChange> &&change)
337{
338 if (this->current_action == nullptr) {
339 if (this->action_type == GLAT_NONE) return;
340
341 this->current_action = &this->data->action.emplace_back();
342 this->current_action->at = this->action_type;
343 this->current_action->tick = TimerGameTick::counter;
344 }
345
346 this->current_action->change.push_back(std::move(change));
347}
348
349
354{
355 /* Terminate any active action */
356 if (this->action_type != GLAT_NONE) this->StopAction();
358 this->Change(std::make_unique<LoggedChangeEmergencySave>());
359 this->StopAction();
360}
361
367{
368 for (const LoggedAction &la : this->data->action) {
369 for (const auto &lc : la.change) {
370 if (lc->ct == GLCT_EMERGENCY) return true;
371 }
372 }
373
374 return false;
375}
376
381{
382 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD);
383
384 this->Change(std::make_unique<LoggedChangeRevision>(
385 GetGamelogRevisionString(), _openttd_newgrf_version, SAVEGAME_VERSION, _openttd_revision_modified));
386}
387
392{
393 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD || this->action_type == GLAT_CHEAT);
394
395 this->Change(std::make_unique<LoggedChangeMode>(_game_mode, _settings_game.game_creation.landscape));
396}
397
402{
403 assert(this->action_type == GLAT_LOAD);
404
405 this->Change(std::make_unique<LoggedChangeOldVersion>(_savegame_type,
407}
408
415void Gamelog::Setting(const std::string &name, int32_t oldval, int32_t newval)
416{
417 assert(this->action_type == GLAT_SETTING);
418
419 this->Change(std::make_unique<LoggedChangeSettingChanged>(name, oldval, newval));
420}
421
422
428{
429 const LoggedChangeRevision *rev = nullptr;
430
431 for (const LoggedAction &la : this->data->action) {
432 for (const auto &lc : la.change) {
433 if (lc->ct == GLCT_REVISION) rev = static_cast<const LoggedChangeRevision *>(lc.get());
434 }
435 }
436
437 if (rev == nullptr || rev->text != GetGamelogRevisionString() ||
438 rev->modified != _openttd_revision_modified ||
439 rev->newgrf != _openttd_newgrf_version) {
440 this->Revision();
441 }
442}
443
449{
450 const LoggedChangeMode *mode = nullptr;
451
452 for (const LoggedAction &la : this->data->action) {
453 for (const auto &lc : la.change) {
454 if (lc->ct == GLCT_MODE) mode = static_cast<const LoggedChangeMode *>(lc.get());
455 }
456 }
457
458 if (mode == nullptr || mode->mode != _game_mode || mode->landscape != _settings_game.game_creation.landscape) this->Mode();
459}
460
461
468void Gamelog::GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
469{
470 assert(this->action_type == GLAT_GRFBUG);
471
472 this->Change(std::make_unique<LoggedChangeGRFBug>(data, grfid, bug));
473}
474
484bool Gamelog::GRFBugReverse(uint32_t grfid, uint16_t internal_id)
485{
486 for (const LoggedAction &la : this->data->action) {
487 for (const auto &lc : la.change) {
488 if (lc->ct == GLCT_GRFBUG) {
489 LoggedChangeGRFBug *bug = static_cast<LoggedChangeGRFBug *>(lc.get());
490 if (bug->grfid == grfid && bug->bug == GRFBug::VehLength && bug->data == internal_id) {
491 return false;
492 }
493 }
494 }
495 }
496
498 this->GRFBug(grfid, GRFBug::VehLength, internal_id);
499 this->StopAction();
500
501 return true;
502}
503
504
510static inline bool IsLoggableGrfConfig(const GRFConfig &g)
511{
513}
514
519void Gamelog::GRFRemove(uint32_t grfid)
520{
521 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_GRF);
522
523 this->Change(std::make_unique<LoggedChangeGRFRemoved>(grfid));
524}
525
530void Gamelog::GRFAdd(const GRFConfig &newg)
531{
532 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_START || this->action_type == GLAT_GRF);
533
534 if (!IsLoggableGrfConfig(newg)) return;
535
536 this->Change(std::make_unique<LoggedChangeGRFAdd>(newg.ident));
537}
538
545{
546 assert(this->action_type == GLAT_LOAD || this->action_type == GLAT_GRF);
547
548 this->Change(std::make_unique<LoggedChangeGRFChanged>(newg));
549}
550
556void Gamelog::GRFMove(uint32_t grfid, int32_t offset)
557{
558 assert(this->action_type == GLAT_GRF);
559
560 this->Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
561}
562
568void Gamelog::GRFParameters(uint32_t grfid)
569{
570 assert(this->action_type == GLAT_GRF);
571
572 this->Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
573}
574
580void Gamelog::GRFAddList(const GRFConfigList &newg)
581{
582 assert(this->action_type == GLAT_START || this->action_type == GLAT_LOAD);
583
584 for (const auto &c : newg) {
585 this->GRFAdd(*c);
586 }
587}
588
594static std::vector<const GRFConfig *> GenerateGRFList(const GRFConfigList &grfc)
595{
596 std::vector<const GRFConfig *> list;
597 for (const auto &g : grfc) {
598 if (IsLoggableGrfConfig(*g)) list.push_back(g.get());
599 }
600
601 return list;
602}
603
609void Gamelog::GRFUpdate(const GRFConfigList &oldc, const GRFConfigList &newc)
610{
611 std::vector<const GRFConfig *> ol = GenerateGRFList(oldc);
612 std::vector<const GRFConfig *> nl = GenerateGRFList(newc);
613
614 uint o = 0, n = 0;
615
616 while (o < ol.size() && n < nl.size()) {
617 const GRFConfig &og = *ol[o];
618 const GRFConfig &ng = *nl[n];
619
620 if (og.ident.grfid != ng.ident.grfid) {
621 uint oi, ni;
622 for (oi = 0; oi < ol.size(); oi++) {
623 if (ol[oi]->ident.grfid == nl[n]->ident.grfid) break;
624 }
625 if (oi < o) {
626 /* GRF was moved, this change has been logged already */
627 n++;
628 continue;
629 }
630 if (oi == ol.size()) {
631 /* GRF couldn't be found in the OLD list, GRF was ADDED */
632 this->GRFAdd(*nl[n++]);
633 continue;
634 }
635 for (ni = 0; ni < nl.size(); ni++) {
636 if (nl[ni]->ident.grfid == ol[o]->ident.grfid) break;
637 }
638 if (ni < n) {
639 /* GRF was moved, this change has been logged already */
640 o++;
641 continue;
642 }
643 if (ni == nl.size()) {
644 /* GRF couldn't be found in the NEW list, GRF was REMOVED */
645 this->GRFRemove(ol[o++]->ident.grfid);
646 continue;
647 }
648
649 /* o < oi < ol->n
650 * n < ni < nl->n */
651 assert(ni > n && ni < nl.size());
652 assert(oi > o && oi < ol.size());
653
654 ni -= n; // number of GRFs it was moved downwards
655 oi -= o; // number of GRFs it was moved upwards
656
657 if (ni >= oi) { // prefer the one that is moved further
658 /* GRF was moved down */
659 this->GRFMove(ol[o++]->ident.grfid, ni);
660 } else {
661 this->GRFMove(nl[n++]->ident.grfid, -(int)oi);
662 }
663 } else {
664 if (og.ident.md5sum != ng.ident.md5sum) {
665 /* md5sum changed, probably loading 'compatible' GRF */
666 this->GRFCompatible(nl[n]->ident);
667 }
668
669 if (og.param != ng.param) {
670 this->GRFParameters(ol[o]->ident.grfid);
671 }
672
673 o++;
674 n++;
675 }
676 }
677
678 while (o < ol.size()) this->GRFRemove(ol[o++]->ident.grfid); // remaining GRFs were removed ...
679 while (n < nl.size()) this->GRFAdd (*nl[n++]); // ... or added
680}
681
688void Gamelog::Info(uint32_t *last_ottd_rev, uint8_t *ever_modified, bool *removed_newgrfs)
689{
690 for (const LoggedAction &la : this->data->action) {
691 for (const auto &lc : la.change) {
692 switch (lc->ct) {
693 default: break;
694
695 case GLCT_REVISION: {
696 const LoggedChangeRevision *rev = static_cast<const LoggedChangeRevision *>(lc.get());
697 *last_ottd_rev = rev->newgrf;
698 *ever_modified = std::max(*ever_modified, rev->modified);
699 break;
700 }
701
702 case GLCT_GRFREM:
703 *removed_newgrfs = true;
704 break;
705 }
706 }
707 }
708}
709
716{
717 const LoggedAction &la = this->data->action.back();
718 if (la.at != GLAT_LOAD) return c.ident;
719
720 for (const auto &lc : la.change) {
721 if (lc->ct != GLCT_GRFCOMPAT) continue;
722
723 const LoggedChangeGRFChanged &grf = *static_cast<const LoggedChangeGRFChanged *>(lc.get());
724 if (grf.grfid == c.ident.grfid) return grf;
725 }
726
727 return c.ident;
728}
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:427
const GRFIdentifier & GetOverriddenIdentifier(const GRFConfig &c)
Try to find the overridden GRF identifier of the given GRF.
Definition gamelog.cpp:715
void Mode()
Logs a change in game mode (scenario editor or game).
Definition gamelog.cpp:391
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:688
void PrintDebug(int level)
Prints gamelog to debug output.
Definition gamelog.cpp:324
void PrintConsole()
Print the gamelog data to the console.
Definition gamelog.cpp:311
void GRFParameters(uint32_t grfid)
Logs change in GRF parameters.
Definition gamelog.cpp:568
void Revision()
Logs a change in game revision.
Definition gamelog.cpp:380
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(uint32_t grfid)
Logs removal of a GRF.
Definition gamelog.cpp:519
void GRFAddList(const GRFConfigList &newg)
Logs adding of list of GRFs.
Definition gamelog.cpp:580
~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:544
void Oldver()
Logs loading from savegame without gamelog.
Definition gamelog.cpp:401
void Emergency()
Logs a emergency savegame.
Definition gamelog.cpp:353
bool GRFBugReverse(uint32_t grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition gamelog.cpp:484
void TestMode()
Finds last stored game mode or landscape.
Definition gamelog.cpp:448
void StopAction()
Stops logging of any changes.
Definition gamelog.cpp:76
void Setting(const std::string &name, int32_t oldval, int32_t newval)
Logs change in game settings.
Definition gamelog.cpp:415
void Print(std::function< void(const std::string &)> proc)
Prints active gamelog.
Definition gamelog.cpp:148
void GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
Logs triggered GRF bug.
Definition gamelog.cpp:468
void GRFAdd(const GRFConfig &newg)
Logs adding of a GRF.
Definition gamelog.cpp:530
void GRFUpdate(const GRFConfigList &oldg, const GRFConfigList &newg)
Compares two NewGRF lists and logs any change.
Definition gamelog.cpp:609
void Change(std::unique_ptr< LoggedChange > &&change)
Allocates a new LoggedAction if needed, and add the change when action is active.
Definition gamelog.cpp:336
bool TestEmergency()
Finds out if current game is a loaded emergency savegame.
Definition gamelog.cpp:366
void GRFMove(uint32_t grfid, int32_t offset)
Logs changing GRF order.
Definition gamelog.cpp:556
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:49
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:110
static bool IsLoggableGrfConfig(const GRFConfig &g)
Decides if GRF should be logged.
Definition gamelog.cpp:510
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:132
static std::vector< const GRFConfig * > GenerateGRFList(const GRFConfigList &grfc)
Generates GRFList.
Definition gamelog.cpp:594
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:304
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:231
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:293
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:264
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:283
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:274
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:242
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:172
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:193
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:178
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:225
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.