35 this->data = std::make_unique<GamelogInternalData>();
37 this->current_action =
nullptr;
49 if (IsReleasedVersion()) {
50 return _openttd_revision;
54 assert(_openttd_revision_modified < 3);
55 return fmt::format(
"{}{}",
56 "gum"[_openttd_revision_modified],
57 _openttd_revision_hash);
68 this->action_type = at;
78 bool print = this->current_action !=
nullptr;
80 this->current_action =
nullptr;
86 void Gamelog::StopAnyAction()
97 this->data->action.clear();
98 this->current_action =
nullptr;
109 static void AddGrfInfo(std::back_insert_iterator<std::string> &output_iterator, uint32_t grfid,
const MD5Hash *md5sum,
const GRFConfig *gc)
111 if (md5sum !=
nullptr) {
114 fmt::format_to(output_iterator,
"GRF ID {:08X}",
BSWAP32(grfid));
118 fmt::format_to(output_iterator,
", filename: {} (md5sum matches)", gc->
filename);
122 fmt::format_to(output_iterator,
", filename: {} (matches GRFID only)", gc->
filename);
124 fmt::format_to(output_iterator,
", unknown GRF");
134 "GRF config changed",
138 "emergency savegame",
149 GrfIDMapping grf_names;
151 proc(
"---- gamelog start ----");
158 for (
auto &lc : la.
change) {
160 auto output_iterator = std::back_inserter(message);
161 lc->FormatTo(output_iterator, grf_names, la.
at);
167 proc(
"---- gamelog end ----");
171 void LoggedChangeMode::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &,
GamelogActionType)
174 fmt::format_to(output_iterator,
"New game mode: {} landscape: {}", this->
mode, this->
landscape);
177 void LoggedChangeRevision::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &,
GamelogActionType)
180 fmt::format_to(output_iterator,
"Revision text changed to {}, savegame version {}, ",
183 switch (this->modified) {
184 case 0: fmt::format_to(output_iterator,
"not ");
break;
185 case 1: fmt::format_to(output_iterator,
"maybe ");
break;
189 fmt::format_to(output_iterator,
"modified, _openttd_newgrf_version = 0x{:08x}", this->
newgrf);
192 void LoggedChangeOldVersion::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &,
GamelogActionType)
195 fmt::format_to(output_iterator,
"Conversion from ");
196 switch (this->
type) {
197 default: NOT_REACHED();
199 fmt::format_to(output_iterator,
"OTTD savegame without gamelog: version {}, {}",
204 fmt::format_to(output_iterator,
"TTO savegame");
208 fmt::format_to(output_iterator,
"TTD savegame");
213 fmt::format_to(output_iterator,
"TTDP savegame, {} format",
216 fmt::format_to(output_iterator,
", TTDP version {}.{}.{}.{}",
224 void LoggedChangeSettingChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &,
GamelogActionType)
227 fmt::format_to(output_iterator,
"Setting changed: {} : {} -> {}", this->
name, this->
oldval, this->
newval);
230 void LoggedChangeGRFAdd::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names,
GamelogActionType)
234 fmt::format_to(output_iterator,
"Added NewGRF: ");
236 auto gm = grf_names.find(this->
grfid);
237 if (gm != grf_names.end() && !gm->second.was_missing) fmt::format_to(output_iterator,
". Gamelog inconsistency: GrfID was already added!");
238 grf_names[this->
grfid] = gc;
241 void LoggedChangeGRFRemoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names,
GamelogActionType action_type)
244 auto gm = grf_names.find(this->
grfid);
246 fmt::format_to(output_iterator,
"Missing NewGRF: ");
248 fmt::format_to(output_iterator,
"Removed NewGRF: ");
250 AddGrfInfo(output_iterator, this->
grfid,
nullptr, gm != grf_names.end() ? gm->second.gc :
nullptr);
251 if (gm == grf_names.end()) {
252 fmt::format_to(output_iterator,
". Gamelog inconsistency: GrfID was never added!");
256 gm->second.was_missing =
true;
263 void LoggedChangeGRFChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names,
GamelogActionType)
267 fmt::format_to(output_iterator,
"Compatible NewGRF loaded: ");
269 if (grf_names.count(this->grfid) == 0) fmt::format_to(output_iterator,
". Gamelog inconsistency: GrfID was never added!");
270 grf_names[this->
grfid] = gc;
273 void LoggedChangeGRFParameterChanged::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names,
GamelogActionType)
276 auto gm = grf_names.find(this->
grfid);
277 fmt::format_to(output_iterator,
"GRF parameter changed: ");
278 AddGrfInfo(output_iterator, this->
grfid,
nullptr, gm != grf_names.end() ? gm->second.gc :
nullptr);
279 if (gm == grf_names.end()) fmt::format_to(output_iterator,
". Gamelog inconsistency: GrfID was never added!");
282 void LoggedChangeGRFMoved::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names,
GamelogActionType)
285 auto gm = grf_names.find(this->
grfid);
286 fmt::format_to(output_iterator,
"GRF order changed: {:08X} moved {} places {}",
288 AddGrfInfo(output_iterator, this->
grfid,
nullptr, gm != grf_names.end() ? gm->second.gc :
nullptr);
289 if (gm == grf_names.end()) fmt::format_to(output_iterator,
". Gamelog inconsistency: GrfID was never added!");
292 void LoggedChangeGRFBug::FormatTo(std::back_insert_iterator<std::string> &output_iterator, GrfIDMapping &grf_names,
GamelogActionType)
295 auto gm = grf_names.find(this->
grfid);
298 fmt::format_to(output_iterator,
"Rail vehicle changes length outside a depot: GRF ID {:08X}, internal ID 0x{:X}",
BSWAP32(this->
grfid), this->
data);
299 AddGrfInfo(output_iterator, this->
grfid,
nullptr, gm != grf_names.end() ? gm->second.gc :
nullptr);
300 if (gm == grf_names.end()) fmt::format_to(output_iterator,
". Gamelog inconsistency: GrfID was never added!");
303 void LoggedChangeEmergencySave::FormatTo(std::back_insert_iterator<std::string> &, GrfIDMapping &,
GamelogActionType)
312 this->
Print([](
const std::string &s) {
325 this->
Print([level](
const std::string &s) {
326 Debug(gamelog, level,
"{}", s);
337 if (this->current_action ==
nullptr) {
338 if (this->action_type ==
GLAT_NONE)
return;
340 this->current_action = &this->data->action.emplace_back();
341 this->current_action->
at = this->action_type;
345 this->current_action->
change.push_back(std::move(change));
357 this->
Change(std::make_unique<LoggedChangeEmergencySave>());
367 for (
const auto &lc : la.
change) {
382 this->
Change(std::make_unique<LoggedChangeRevision>(
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));
556 assert(this->action_type ==
GLAT_GRF);
558 this->
Change(std::make_unique<LoggedChangeGRFMoved>(grfid, offset));
568 assert(this->action_type ==
GLAT_GRF);
570 this->
Change(std::make_unique<LoggedChangeGRFParameterChanged>(grfid));
582 for (; newg !=
nullptr; newg = newg->
next) {
593 std::vector<const GRFConfig *> list;
613 while (o < ol.size() && n < nl.size()) {
619 for (oi = 0; oi < ol.size(); oi++) {
620 if (ol[oi]->ident.grfid == nl[n]->ident.grfid)
break;
627 if (oi == ol.size()) {
632 for (ni = 0; ni < nl.size(); ni++) {
633 if (nl[ni]->ident.grfid == ol[o]->ident.grfid)
break;
640 if (ni == nl.size()) {
648 assert(ni > n && ni < nl.size());
649 assert(oi > o && oi < ol.size());
656 this->
GRFMove(ol[o++]->ident.grfid, ni);
658 this->
GRFMove(nl[n++]->ident.grfid, -(
int)oi);
675 while (o < ol.size()) this->
GRFRemove(ol[o++]->ident.grfid);
676 while (n < nl.size()) this->
GRFAdd (nl[n++]);
685 void Gamelog::Info(uint32_t *last_ottd_rev,
byte *ever_modified,
bool *removed_newgrfs)
688 for (
const auto &lc : la.
change) {
694 *last_ottd_rev = rev->
newgrf;
695 *ever_modified = std::max(*ever_modified, rev->modified);
700 *removed_newgrfs =
true;
714 assert(c !=
nullptr);
718 for (
const auto &lc : la.
change) {