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,
GrfID 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 proc(
"---- gamelog start ----");
157 for (
auto &lc : la.
change) {
159 auto output_iterator = std::back_inserter(message);
160 lc->FormatTo(output_iterator, grf_names, la.
at);
166 proc(
"---- gamelog end ----");
173 fmt::format_to(output_iterator,
"New game mode: {} landscape: {}", this->
mode, this->
landscape);
179 fmt::format_to(output_iterator,
"Revision text changed to {}, savegame version {}, ",
183 case 0: fmt::format_to(output_iterator,
"not ");
break;
184 case 1: fmt::format_to(output_iterator,
"maybe ");
break;
188 fmt::format_to(output_iterator,
"modified, _openttd_newgrf_version = 0x{:08x}", this->
newgrf);
194 fmt::format_to(output_iterator,
"Conversion from ");
195 switch (this->
type) {
196 default: NOT_REACHED();
198 fmt::format_to(output_iterator,
"OTTD savegame without gamelog: version {}, {}",
203 fmt::format_to(output_iterator,
"TTO savegame");
207 fmt::format_to(output_iterator,
"TTD savegame");
212 fmt::format_to(output_iterator,
"TTDP savegame, {} format",
215 fmt::format_to(output_iterator,
", TTDP version {}.{}.{}.{}",
226 fmt::format_to(output_iterator,
"Setting changed: {} : {} -> {}", this->
name, this->
oldval, this->
newval);
233 fmt::format_to(output_iterator,
"Added NewGRF: ");
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;
243 auto gm = grf_names.find(this->
grfid);
245 fmt::format_to(output_iterator,
"Missing NewGRF: ");
247 fmt::format_to(output_iterator,
"Removed NewGRF: ");
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!");
255 gm->second.was_missing =
true;
266 fmt::format_to(output_iterator,
"Compatible NewGRF loaded: ");
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;
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!");
284 auto gm = grf_names.find(this->
grfid);
285 fmt::format_to(output_iterator,
"GRF order changed: {:08X} moved {} places {}",
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!");
294 auto gm = grf_names.find(this->
grfid);
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!");
311 this->
Print([](
const std::string &s) {
324 this->
Print([level](
const std::string &s) {
325 Debug(gamelog, level,
"{}", s);
336 if (this->current_action ==
nullptr) {
339 this->current_action = &this->data->action.emplace_back();
340 this->current_action->at = this->action_type;
344 this->current_action->change.push_back(std::move(change));
356 this->
Change(std::make_unique<LoggedChangeEmergencySave>());
367 for (
const auto &lc : la.
change) {
382 this->
Change(std::make_unique<LoggedChangeRevision>(
393 this->
Change(std::make_unique<LoggedChangeMode>(_game_mode,
_settings_game.game_creation.landscape));
417 this->
Change(std::make_unique<LoggedChangeSettingChanged>(name, oldval, newval));
430 for (
const auto &lc : la.
change) {
436 rev->
modified != _openttd_revision_modified ||
437 rev->
newgrf != _openttd_newgrf_version) {
451 for (
const auto &lc : la.
change) {
470 this->
Change(std::make_unique<LoggedChangeGRFBug>(data, grfid, bug));
485 for (
const auto &lc : la.
change) {
521 this->
Change(std::make_unique<LoggedChangeGRFRemoved>(grfid));
534 this->
Change(std::make_unique<LoggedChangeGRFAdd>(newg.
ident));
546 this->
Change(std::make_unique<LoggedChangeGRFChanged>(newg));
558 this->
Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
570 this->
Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
582 for (
const auto &c : newg) {
594 std::vector<const GRFConfig *> list;
595 for (
const auto &g : grfc) {
614 while (o < ol.size() && n < nl.size()) {
620 for (oi = 0; oi < ol.size(); oi++) {
621 if (ol[oi]->ident.grfid == nl[n]->ident.grfid)
break;
628 if (oi == ol.size()) {
633 for (ni = 0; ni < nl.size(); ni++) {
634 if (nl[ni]->ident.grfid == ol[o]->ident.grfid)
break;
641 if (ni == nl.size()) {
649 assert(ni > n && ni < nl.size());
650 assert(oi > o && oi < ol.size());
657 this->
GRFMove(ol[o++]->ident.grfid, ni);
659 this->
GRFMove(nl[n++]->ident.grfid, -(
int)oi);
676 while (o < ol.size()) this->
GRFRemove(ol[o++]->ident.grfid);
677 while (n < nl.size()) this->
GRFAdd (*nl[n++]);
686void Gamelog::Info(uint32_t *last_ottd_rev, uint8_t *ever_modified,
bool *removed_newgrfs)
689 for (
const auto &lc : la.
change) {
695 *last_ottd_rev = rev->
newgrf;
696 *ever_modified = std::max(*ever_modified, rev->
modified);
701 *removed_newgrfs =
true;
718 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.
bool GRFBugReverse(GrfID grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
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(GrfID 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(GrfID grfid)
Logs removal of a GRF.
void GRFMove(GrfID grfid, int32_t offset)
Logs changing GRF order.
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.
void TestMode()
Finds last stored game mode or landscape.
void StopAction()
Stops logging of any changes.
void GRFBug(GrfID grfid, ::GRFBug bug, uint64_t data)
Logs triggered GRF bug.
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 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.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
void IConsolePrint(ExtendedTextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
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.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
uint32_t _ttdp_version
version of TTDP savegame (if applicable)
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 bool IsLoggableGrfConfig(const GRFConfig &g)
Decides if GRF should be logged.
static constexpr EnumIndexArray< std::string_view, GamelogActionType, GamelogActionType::End > la_text
Text messages for various logged actions.
SavegameType _savegame_type
type of savegame we are loading
static std::vector< const GRFConfig * > GenerateGRFList(const GRFConfigList &grfc)
Generates GRFList.
const SaveLoadVersion SAVEGAME_VERSION
current savegame version
static void AddGrfInfo(std::back_insert_iterator< std::string > &output_iterator, GrfID grfid, const MD5Hash *md5sum, const GRFConfig *gc)
Adds the GRF ID, checksum and filename if found to the output iterator.
@ GRFCompat
Loading compatible GRF.
@ Revision
Changed game revision string.
@ Mode
Scenario editor x Game, different landscape.
@ Emergency
Emergency savegame.
@ GRFBug
GRF bug triggered.
GamelogActionType
The actions we log.
@ Setting
Setting changed.
@ None
No logging active; in savegames, end of list.
@ Emergency
Emergency savegame.
@ GRFBug
GRF bug was triggered.
Declaration shared among gamelog.cpp and saveload/gamelog_sl.cpp.
std::map< GrfID, GRFPresence > GrfIDMapping
A mapping from GrfID to the GRFPresence.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
const GRFConfig * FindGRFConfig(GrfID grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
@ NotFound
GRF file was not found in the local cache.
@ Static
GRF file is used statically (can be used in any MP game).
GRFBug
Encountered GRF bugs.
@ VehLength
Length of rail vehicle changes when not inside a depot.
@ Exact
Only find Grfs matching md5sum.
uint32_t GrfID
The unique identifier of a NewGRF.
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.
@ TTDP1
TTDP savegame ( -//- ) (data at NW border).
@ TTD
TTD savegame (can be detected incorrectly).
@ TTDP2
TTDP savegame in new format (data at SE 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.
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.
GrfID grfid
GRF ID (defined by Action 0x08).
MD5Hash md5sum
MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF).
Contains information about one logged action that caused at least one logged change.
uint64_t tick
Tick when it happened.
std::vector< std::unique_ptr< LoggedChange > > change
Logged changes in this action.
GamelogActionType at
Type of action.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
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.
A log entry for a NewGRF 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.
GrfID grfid
ID of problematic GRF.
uint64_t data
additional data
A log entry for a NewGRF that was changed.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
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.
int32_t offset
offset, positive = move down
GrfID grfid
ID of moved GRF.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
GrfID grfid
ID of GRF with changed parameters.
GrfID grfid
ID of removed GRF.
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
Log element for the change of the game mode and landscape.
LandscapeType landscape
landscape (temperate, arctic, ...)
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
GameMode mode
new game mode - Editor x Game
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
uint32_t type
type of savegame,
uint32_t version
major and minor version OR ttdp version
A log entry for a change in OpenTTD version.
std::string text
revision string, _openttd_revision
void FormatTo(std::back_insert_iterator< std::string > &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) override
Format the content of this change into the given output.
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.