diff --git a/src/openttd.cpp b/src/openttd.cpp index 0e45e97ce4..b606c8b1e2 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1530,6 +1530,9 @@ void CheckCaches(bool force_check, std::function log) if (tv->Next()) assert_msg(tv->Next()->Prev() == tv, "%u", tv->index); } + if (!TraceRestrictSlot::ValidateVehicleIndex()) CCLOG("Trace restrict slot vehicle index validation failed"); + TraceRestrictSlot::ValidateSlotOccupants(log); + #undef CCLOG } diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index b839865696..b631831acb 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -21,6 +21,7 @@ #include "group.h" #include "string_func.h" #include "pathfinder/yapf/yapf_cache.h" +#include "scope_info.h" #include #include @@ -1692,6 +1693,39 @@ void TraceRestrictSlot::RebuildVehicleIndex() } } +bool TraceRestrictSlot::ValidateVehicleIndex() +{ + std::unordered_multimap saved_slot_vehicle_index = std::move(slot_vehicle_index); + RebuildVehicleIndex(); + const bool ok = slot_vehicle_index == saved_slot_vehicle_index; + slot_vehicle_index = std::move(saved_slot_vehicle_index); + return ok; +} + +void TraceRestrictSlot::ValidateSlotOccupants(std::function log) +{ + char cclog_buffer[1024]; +#define CCLOG(...) { \ + seprintf(cclog_buffer, lastof(cclog_buffer), __VA_ARGS__); \ + DEBUG(desync, 0, "%s", cclog_buffer); \ + if (log) log(cclog_buffer); \ +} + + const TraceRestrictSlot *slot; + FOR_ALL_TRACE_RESTRICT_SLOTS(slot) { + for (VehicleID id : slot->occupants) { + const Train *t = Train::GetIfValid(id); + if (t) { + if (!t->IsFrontEngine()) CCLOG("Slot %u (%s) has non-front engine train: %s", slot->index, slot->name.c_str(), scope_dumper().VehicleInfo(t)); + if (!HasBit(t->flags, VRF_HAVE_SLOT)) CCLOG("Slot %u (%s) has train without VRF_HAVE_SLOT: %s", slot->index, slot->name.c_str(), scope_dumper().VehicleInfo(t)); + } else { + CCLOG("Slot %u (%s) has non-existent vehicle ID: %u", slot->index, slot->name.c_str(), id); + } + } + } +#undef CCLOG +} + /** Slot pool is about to be cleared */ void TraceRestrictSlot::PreCleanPool() { diff --git a/src/tracerestrict.h b/src/tracerestrict.h index c4554deab9..b85b9767ab 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -817,6 +817,8 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p OwnerByte owner; static void RebuildVehicleIndex(); + static bool ValidateVehicleIndex(); + static void ValidateSlotOccupants(std::function log); static void PreCleanPool(); TraceRestrictSlot(CompanyID owner = INVALID_COMPANY)