From 64a36d89e1c8c35a6e92e1cfb9d57cb9224c93a6 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 15 Mar 2026 19:23:54 +0100 Subject: [PATCH 1/4] feat: more detailed logs about what is being loaded --- src/ObjLoading/Asset/AssetCreationContext.cpp | 39 ++++++++++++++----- src/ObjLoading/Asset/AssetCreationContext.h | 2 + 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/ObjLoading/Asset/AssetCreationContext.cpp b/src/ObjLoading/Asset/AssetCreationContext.cpp index 1e19f6ab..969374b4 100644 --- a/src/ObjLoading/Asset/AssetCreationContext.cpp +++ b/src/ObjLoading/Asset/AssetCreationContext.cpp @@ -66,6 +66,7 @@ std::unique_ptr GenericAssetRegistration::CreateXAssetInfo() AssetCreationContext::AssetCreationContext(Zone& zone, const AssetCreatorCollection* creators, const IgnoredAssetLookup* ignoredAssetLookup) : ZoneAssetCreationStateContainer(zone), m_zone(zone), + m_game(*IGame::GetGameById(zone.m_game_id)), m_forced_asset_pools(std::make_unique(zone, zone.m_priority)), m_creators(creators), m_ignored_asset_lookup(ignoredAssetLookup), @@ -141,6 +142,8 @@ XAssetInfoGeneric* AssetCreationContext::LoadDependencyGeneric(const asset_type_ return LoadDefaultAssetDependency(assetType, std::format(",{}", assetName)); } + const auto assetTypeName = m_game.GetAssetTypeName(assetType).value_or("unknown"); + if (m_ignored_asset_lookup->IsAssetIgnored(assetType, assetName)) return LoadDefaultAssetDependency(assetType, std::format(",{}", assetName)); @@ -148,13 +151,16 @@ XAssetInfoGeneric* AssetCreationContext::LoadDependencyGeneric(const asset_type_ if (result.HasTakenAction()) { if (!result.HasFailed()) + { + con::info(R"(Loaded {} "{}")", assetTypeName, assetName); return result.GetAssetInfo(); + } - con::error(R"(Could not load asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetAssetTypeName(assetType)); + con::error(R"(Could not load asset "{}" of type "{}")", assetName, assetTypeName); } else if (required) { - con::error(R"(Missing asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetAssetTypeName(assetType)); + con::error(R"(Missing asset "{}" of type "{}")", assetName, assetTypeName); } return nullptr; @@ -167,17 +173,22 @@ XAssetInfoGeneric* AssetCreationContext::LoadSubAssetGeneric(const asset_type_t if (alreadyLoadedSubAsset) return alreadyLoadedSubAsset; + const auto subAssetTypeName = m_game.GetSubAssetTypeName(subAssetType).value_or("unknown"); + const auto result = m_creators->CreateSubAsset(subAssetType, assetName, *this); if (result.HasTakenAction()) { if (!result.HasFailed()) + { + con::debug(R"(Loaded {} "{}")", subAssetTypeName, assetName); return result.GetAssetInfo(); + } - con::error(R"(Could not load sub asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetSubAssetTypeName(subAssetType)); + con::error(R"(Could not load sub asset "{}" of type "{}")", assetName, subAssetTypeName); } else { - con::error(R"(Missing sub asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetSubAssetTypeName(subAssetType)); + con::error(R"(Missing sub asset "{}" of type "{}")", assetName, subAssetTypeName); } return nullptr; @@ -192,12 +203,17 @@ IndirectAssetReference AssetCreationContext::LoadIndirectAssetReferenceGeneric(c if (m_ignored_asset_lookup->IsAssetIgnored(assetType, assetName)) return IndirectAssetReference(assetType, assetName); + const auto assetTypeName = m_game.GetAssetTypeName(assetType).value_or("unknown"); const auto result = m_creators->CreateAsset(assetType, assetName, *this); - if (!result.HasTakenAction() && !result.HasFailed()) + if (result.HasTakenAction() && !result.HasFailed()) { - con::warn( - R"(Could not load indirectly referenced asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetAssetTypeName(assetType)); + con::info(R"(Loaded {} "{}")", assetTypeName, assetName); } + else if (!result.HasTakenAction() && !result.HasFailed()) + { + con::warn(R"(Could not load indirectly referenced asset "{}" of type "{}")", assetName, assetTypeName); + } + return IndirectAssetReference(assetType, assetName); } @@ -227,16 +243,21 @@ XAssetInfoGeneric* AssetCreationContext::ForceLoadDependencyGeneric(const asset_ else result = m_creators->CreateAsset(assetType, assetName, *this); + const auto assetTypeName = m_game.GetAssetTypeName(assetType).value_or("unknown"); + if (result.HasTakenAction()) { if (!result.HasFailed()) + { + con::info(R"(Loaded {} "{}")", assetTypeName, assetName); return result.GetAssetInfo(); + } - con::error(R"(Could not load asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetAssetTypeName(assetType)); + con::error(R"(Could not load asset "{}" of type "{}")", assetName, assetTypeName); } else { - con::error(R"(Missing asset "{}" of type "{}")", assetName, *IGame::GetGameById(m_zone.m_game_id)->GetAssetTypeName(assetType)); + con::error(R"(Missing asset "{}" of type "{}")", assetName, assetTypeName); } return nullptr; diff --git a/src/ObjLoading/Asset/AssetCreationContext.h b/src/ObjLoading/Asset/AssetCreationContext.h index 501da641..f670ecf6 100644 --- a/src/ObjLoading/Asset/AssetCreationContext.h +++ b/src/ObjLoading/Asset/AssetCreationContext.h @@ -3,6 +3,7 @@ #include "Asset/IZoneAssetCreationState.h" #include "AssetRegistration.h" #include "Game/IAsset.h" +#include "Game/IGame.h" #include "Pool/AssetPool.h" #include "Pool/XAssetInfo.h" #include "Zone/AssetList/AssetList.h" @@ -99,6 +100,7 @@ private: [[nodiscard]] XAssetInfoGeneric* LoadDefaultAssetDependency(asset_type_t assetType, const std::string& assetName); Zone& m_zone; + IGame& m_game; std::unique_ptr m_forced_asset_pools; std::vector> m_sub_asset_pools; const AssetCreatorCollection* m_creators; From 3da04f8092de2c7d4c7f5460b25b02cdc5903ab9 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 15 Mar 2026 22:47:46 +0100 Subject: [PATCH 2/4] feat: more details about which assets are dumped --- src/ObjWriting/Dumping/AbstractAssetDumper.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ObjWriting/Dumping/AbstractAssetDumper.h b/src/ObjWriting/Dumping/AbstractAssetDumper.h index 3d85433b..a2e493b1 100644 --- a/src/ObjWriting/Dumping/AbstractAssetDumper.h +++ b/src/ObjWriting/Dumping/AbstractAssetDumper.h @@ -3,6 +3,7 @@ #include "Game/IAsset.h" #include "IAssetDumper.h" #include "Pool/AssetPool.h" +#include "Utils/Logging/Log.h" template class AbstractAssetDumper : public IAssetDumper { @@ -21,6 +22,8 @@ public: void Dump(AssetDumpingContext& context) override { + const auto assetTypeName = IGame::GetGameById(context.m_zone.m_game_id)->GetAssetTypeName(Asset_t::EnumEntry).value_or("unknown"); + for (const auto* assetInfo : context.m_zone.m_pools.PoolAssets()) { if (assetInfo->IsReference() || !ShouldDump(*assetInfo)) @@ -30,6 +33,7 @@ public: } DumpAsset(context, *assetInfo); + con::info("Dumped {} \"{}\"", assetTypeName, assetInfo->m_name); context.IncrementProgress(); } } From 58ab46413a33d61eda2b5083cec56bee0fe21333 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 15 Mar 2026 23:06:56 +0100 Subject: [PATCH 3/4] chore: prefix warn and error messages --- src/Utils/Utils/Logging/Log.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Utils/Utils/Logging/Log.cpp b/src/Utils/Utils/Logging/Log.cpp index 172810b2..4cf7db50 100644 --- a/src/Utils/Utils/Logging/Log.cpp +++ b/src/Utils/Utils/Logging/Log.cpp @@ -89,16 +89,16 @@ namespace con void _warn_internal(const std::string& str) { if (globalUseColor) - std::cout << std::format("\x1B[33m{}\x1B[0m\n", str); + std::cout << std::format("\x1B[33mWARN: {}\x1B[0m\n", str); else - std::cout << std::format("{}\n", str); + std::cout << std::format("WARN: {}\n", str); } void _error_internal(const std::string& str) { if (globalUseColor) - std::cerr << std::format("\x1B[31m{}\x1B[0m\n", str); + std::cerr << std::format("\x1B[31mERROR: {}\x1B[0m\n", str); else - std::cerr << std::format("{}\n", str); + std::cerr << std::format("ERROR: {}\n", str); } } // namespace con From 914cdda3606e7a355f26384b9742232a5f08b9ef Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Mon, 16 Mar 2026 00:46:14 +0100 Subject: [PATCH 4/4] feat: summarize warnings and errors after linking and unlinking --- src/Linking/Linker.cpp | 10 +++++++++- src/Unlinking/Unlinker.cpp | 9 +++++++++ src/Utils/Utils/Logging/Log.cpp | 18 ++++++++++++++++++ src/Utils/Utils/Logging/Log.h | 11 +++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/Linking/Linker.cpp b/src/Linking/Linker.cpp index dc710d4d..0b35d380 100644 --- a/src/Linking/Linker.cpp +++ b/src/Linking/Linker.cpp @@ -155,7 +155,7 @@ namespace class LinkerImpl final : public Linker { public: - LinkerImpl(LinkerArgs args) + explicit LinkerImpl(LinkerArgs args) : m_args(std::move(args)) { } @@ -187,6 +187,8 @@ namespace UnloadZones(); + Summarize(result); + return result; } @@ -464,6 +466,12 @@ namespace return true; } + static void Summarize(const bool result) + { + const char* resultStr = result ? "Finished" : "Failed"; + con::info("{} with {} warnings, {} errors", resultStr, con::warning_count(), con::error_count()); + } + LinkerArgs m_args; std::vector> m_loaded_zones; }; diff --git a/src/Unlinking/Unlinker.cpp b/src/Unlinking/Unlinker.cpp index 771f6bb8..ecdd404d 100644 --- a/src/Unlinking/Unlinker.cpp +++ b/src/Unlinking/Unlinker.cpp @@ -42,6 +42,9 @@ namespace const auto result = UnlinkZones(paths); UnloadZones(); + + Summarize(result); + return result; } @@ -307,6 +310,12 @@ namespace return true; } + static void Summarize(const bool result) + { + const char* resultStr = result ? "Finished" : "Failed"; + con::info("{} with {} warnings, {} errors", resultStr, con::warning_count(), con::error_count()); + } + UnlinkerArgs m_args; std::vector> m_loaded_zones; }; diff --git a/src/Utils/Utils/Logging/Log.cpp b/src/Utils/Utils/Logging/Log.cpp index 4cf7db50..f2611242 100644 --- a/src/Utils/Utils/Logging/Log.cpp +++ b/src/Utils/Utils/Logging/Log.cpp @@ -48,6 +48,8 @@ namespace namespace con { LogLevel _globalLogLevel = LogLevel::INFO; + std::atomic_size_t _warningCount(0); + std::atomic_size_t _errorCount(0); void init() { @@ -70,6 +72,22 @@ namespace con globalUseColor = value && CanUseColor(); } + void reset_counts() + { + _warningCount = 0; + _errorCount = 0; + } + + size_t warning_count() + { + return _warningCount; + } + + size_t error_count() + { + return _errorCount; + } + void _debug_internal(const std::string& str) { if (globalUseColor) diff --git a/src/Utils/Utils/Logging/Log.h b/src/Utils/Utils/Logging/Log.h index f6751e12..814d57d5 100644 --- a/src/Utils/Utils/Logging/Log.h +++ b/src/Utils/Utils/Logging/Log.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -15,11 +16,17 @@ namespace con }; extern LogLevel _globalLogLevel; + extern std::atomic_size_t _warningCount; + extern std::atomic_size_t _errorCount; void init(); void set_log_level(LogLevel value); void set_use_color(bool value); + void reset_counts(); + [[nodiscard]] size_t warning_count(); + [[nodiscard]] size_t error_count(); + void _debug_internal(const std::string& str); void _info_internal(const std::string& str); void _warn_internal(const std::string& str); @@ -55,6 +62,7 @@ namespace con inline void warn(const std::string& str) { + ++_warningCount; if (static_cast(_globalLogLevel) > static_cast(LogLevel::WARN)) return; _warn_internal(str); @@ -62,6 +70,7 @@ namespace con template void warn(std::format_string fmt, Arg0&& arg0, OtherArgs&&... otherArgs) { + ++_warningCount; if (static_cast(_globalLogLevel) > static_cast(LogLevel::WARN)) return; _warn_internal(std::vformat(fmt.get(), std::make_format_args(arg0, otherArgs...))); @@ -69,11 +78,13 @@ namespace con inline void error(const std::string& str) { + ++_errorCount; _error_internal(str); } template void error(std::format_string fmt, Arg0&& arg0, OtherArgs&&... otherArgs) { + ++_errorCount; _error_internal(std::vformat(fmt.get(), std::make_format_args(arg0, otherArgs...))); } } // namespace con