35 this->data = std::make_unique<GamelogInternalData>();
37 this->current_action =
nullptr;
51 if (IsReleasedVersion()) {
52 return _openttd_revision;
56 assert(_openttd_revision_modified < 3);
57 return fmt::format(
"{}{}",
58 "gum"[_openttd_revision_modified],
59 _openttd_revision_hash);
70 this->action_type = at;
80 bool print = this->current_action !=
nullptr;
82 this->current_action =
nullptr;
88void Gamelog::StopAnyAction()
99 this->data->action.clear();
100 this->current_action =
nullptr;
110static void AddGrfInfo(std::back_insert_iterator<std::string> &output_iterator, uint32_t grfid,
const MD5Hash *md5sum,
const GRFConfig *gc)
112 if (md5sum !=
nullptr) {
115 fmt::format_to(output_iterator,
"GRF ID {:08X}",
std::byteswap(grfid));
119 fmt::format_to(output_iterator,
", filename: {} (md5sum matches)", gc->
filename);
123 fmt::format_to(output_iterator,
", filename: {} (matches GRFID only)", gc->
filename);
125 fmt::format_to(output_iterator,
", unknown GRF");
135 "GRF config changed",
139 "emergency savegame",
150 GrfIDMapping grf_names;
152 proc(
"---- gamelog start ----");
159 for (
auto &lc : la.
change) {
161 auto output_iterator = std::back_inserter(message);
162 lc->FormatTo(output_iterator, grf_names, la.
at);
168 proc(
"---- gamelog end ----");
175 fmt::format_to(output_iterator,
"New game mode: {} landscape: {}", this->
mode, this->
landscape);
181 fmt::format_to(output_iterator,
"Revision text changed to {}, savegame version {}, ",
185 case 0: fmt::format_to(output_iterator,
"not ");
break;
186 case 1: fmt::format_to(output_iterator,
"maybe ");
break;
190 fmt::format_to(output_iterator,
"modified, _openttd_newgrf_version = 0x{:08x}", this->
newgrf);
196 fmt::format_to(output_iterator,
"Conversion from ");
197 switch (this->
type) {
198 default: NOT_REACHED();
200 fmt::format_to(output_iterator,
"OTTD savegame without gamelog: version {}, {}",
205 fmt::format_to(output_iterator,
"TTO savegame");
209 fmt::format_to(output_iterator,
"TTD savegame");
214 fmt::format_to(output_iterator,
"TTDP savegame, {} format",
217 fmt::format_to(output_iterator,
", TTDP version {}.{}.{}.{}",
228 fmt::format_to(output_iterator,
"Setting changed: {} : {} -> {}", this->
name, this->
oldval, this->
newval);
235 fmt::format_to(output_iterator,
"Added NewGRF: ");
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;
245 auto gm = grf_names.find(this->
grfid);
247 fmt::format_to(output_iterator,
"Missing NewGRF: ");
249 fmt::format_to(output_iterator,
"Removed NewGRF: ");
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!");
257 gm->second.was_missing =
true;
268 fmt::format_to(output_iterator,
"Compatible NewGRF loaded: ");
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;
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!");
286 auto gm = grf_names.find(this->
grfid);
287 fmt::format_to(output_iterator,
"GRF order changed: {:08X} moved {} places {}",
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!");
296 auto gm = grf_names.find(this->
grfid);
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!");
313 this->
Print([](
const std::string &s) {
326 this->
Print([level](
const std::string &s) {
327 Debug(gamelog, level,
"{}", s);
338 if (this->current_action ==
nullptr) {
339 if (this->action_type ==
GLAT_NONE)
return;
341 this->current_action = &this->data->action.emplace_back();
342 this->current_action->at = this->action_type;
346 this->current_action->change.push_back(std::move(change));
358 this->
Change(std::make_unique<LoggedChangeEmergencySave>());
369 for (
const auto &lc : la.
change) {
384 this->
Change(std::make_unique<LoggedChangeRevision>(
395 this->
Change(std::make_unique<LoggedChangeMode>(_game_mode,
_settings_game.game_creation.landscape));
419 this->
Change(std::make_unique<LoggedChangeSettingChanged>(name, oldval, newval));
432 for (
const auto &lc : la.
change) {
438 rev->
modified != _openttd_revision_modified ||
439 rev->
newgrf != _openttd_newgrf_version) {
453 for (
const auto &lc : la.
change) {
472 this->
Change(std::make_unique<LoggedChangeGRFBug>(data, grfid, bug));
487 for (
const auto &lc : la.
change) {
523 this->
Change(std::make_unique<LoggedChangeGRFRemoved>(grfid));
536 this->
Change(std::make_unique<LoggedChangeGRFAdd>(newg.
ident));
548 this->
Change(std::make_unique<LoggedChangeGRFChanged>(newg));
558 assert(this->action_type ==
GLAT_GRF);
560 this->
Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
570 assert(this->action_type ==
GLAT_GRF);
572 this->
Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
584 for (
const auto &c : newg) {
596 std::vector<const GRFConfig *> list;
597 for (
const auto &g : grfc) {
616 while (o < ol.size() && n < nl.size()) {
622 for (oi = 0; oi < ol.size(); oi++) {
623 if (ol[oi]->ident.grfid == nl[n]->ident.grfid)
break;
630 if (oi == ol.size()) {
635 for (ni = 0; ni < nl.size(); ni++) {
636 if (nl[ni]->ident.grfid == ol[o]->ident.grfid)
break;
643 if (ni == nl.size()) {
651 assert(ni > n && ni < nl.size());
652 assert(oi > o && oi < ol.size());
659 this->
GRFMove(ol[o++]->ident.grfid, ni);
661 this->
GRFMove(nl[n++]->ident.grfid, -(
int)oi);
678 while (o < ol.size()) this->
GRFRemove(ol[o++]->ident.grfid);
679 while (n < nl.size()) this->
GRFAdd (*nl[n++]);
688void Gamelog::Info(uint32_t *last_ottd_rev, uint8_t *ever_modified,
bool *removed_newgrfs)
691 for (
const auto &lc : la.
change) {
697 *last_ottd_rev = rev->
newgrf;
698 *ever_modified = std::max(*ever_modified, rev->
modified);
703 *removed_newgrfs =
true;
720 for (
const auto &lc : la.
change) {
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.
const GRFIdentifier & GetOverriddenIdentifier(const GRFConfig &c)
Try to find the overridden GRF identifier of the given GRF.
void Mode()
Logs a change in game mode (scenario editor or game).
void Info(uint32_t *last_ottd_rev, uint8_t *ever_modified, bool *removed_newgrfs)
Get some basic information from the given gamelog.
void PrintDebug(int level)
Prints gamelog to debug output.
void PrintConsole()
Print the gamelog data to the console.
void GRFParameters(uint32_t grfid)
Logs change in GRF parameters.
void Revision()
Logs a change in game revision.
void StartAction(GamelogActionType at)
Stores information about new action, but doesn't allocate it Action is allocated only when there is a...
void Reset()
Resets and frees all memory allocated - used before loading or starting a new game.
void GRFRemove(uint32_t grfid)
Logs removal of a GRF.
void GRFAddList(const GRFConfigList &newg)
Logs adding of list of GRFs.
~Gamelog()
Needs to be manually defined due to incomplete definition of GamelogInternalData in the header.
void GRFCompatible(const GRFIdentifier &newg)
Logs loading compatible GRF (the same ID, but different MD5 hash).
void Oldver()
Logs loading from savegame without gamelog.
void Emergency()
Logs a emergency savegame.
bool GRFBugReverse(uint32_t grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
void TestMode()
Finds last stored game mode or landscape.
void StopAction()
Stops logging of any changes.
void Setting(const std::string &name, int32_t oldval, int32_t newval)
Logs change in game settings.
void Print(std::function< void(const std::string &)> proc)
Prints active gamelog.
void GRFBug(uint32_t grfid, ::GRFBug bug, uint64_t data)
Logs triggered GRF bug.
void GRFAdd(const GRFConfig &newg)
Logs adding of a GRF.
void GRFUpdate(const GRFConfigList &oldg, const GRFConfigList &newg)
Compares two NewGRF lists and logs any change.
void Change(std::unique_ptr< LoggedChange > &&change)
Allocates a new LoggedAction if needed, and add the change when action is active.
bool TestEmergency()
Finds out if current game is a loaded emergency savegame.
void GRFMove(uint32_t grfid, int32_t offset)
Logs changing GRF order.
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.
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.
uint32_t _ttdp_version
version of TTDP savegame (if applicable)
SaveLoadVersion _sl_version
the major savegame version identifier
uint8_t _sl_minor_version
the minor savegame version, DO NOT USE!
static std::string GetGamelogRevisionString()
Return the revision string for the current client version, for use in gamelog.
Gamelog _gamelog
Gamelog instance.
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.
static bool IsLoggableGrfConfig(const GRFConfig &g)
Decides if GRF should be logged.
SavegameType _savegame_type
type of savegame we are loading
static const std::string_view la_text[]
Text messages for various logged actions.
static std::vector< const GRFConfig * > GenerateGRFList(const GRFConfigList &grfc)
Generates GRFList.
const SaveLoadVersion SAVEGAME_VERSION
current savegame version
@ GLCT_MODE
Scenario editor x Game, different landscape.
@ GLCT_GRFCOMPAT
Loading compatible GRF.
@ GLCT_EMERGENCY
Emergency savegame.
@ GLCT_GRFBUG
GRF bug triggered.
@ GLCT_REVISION
Changed game revision string.
GamelogActionType
The actions we log.
@ GLAT_GRFBUG
GRF bug was triggered.
@ GLAT_START
Game created.
@ GLAT_NONE
No logging active; in savegames, end of list.
@ GLAT_END
So we know how many GLATs are there.
@ GLAT_CHEAT
Cheat was used.
@ GLAT_EMERGENCY
Emergency savegame.
@ GLAT_SETTING
Setting changed.
Declaration shared among gamelog.cpp and saveload/gamelog_sl.cpp.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
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.
@ SGT_TTD
TTD savegame (can be detected incorrectly).
@ SGT_TTDP2
TTDP savegame in new format (data at SE border).
@ SGT_TTDP1
TTDP savegame ( -//- ) (data at NW border).
SaveLoadVersion
SaveLoad versions Previous savegame versions, the trunk revision where they were introduced and the r...
GameSettings _settings_game
Game settings of a running game or the scenario editor.
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.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 of the game-calendar-timer.
Definition of the tick-based game-timer.