diff --git a/src/Common/Game/IGame.h b/src/Common/Game/IGame.h index 89251a79..b57c0e9b 100644 --- a/src/Common/Game/IGame.h +++ b/src/Common/Game/IGame.h @@ -1,10 +1,31 @@ #pragma once #include "GameLanguage.h" +#include #include class Zone; +enum class GameId +{ + IW3, + IW4, + IW5, + T5, + T6, + + COUNT +}; + +static constexpr const char* GameId_Names[]{ + "IW3", + "IW4", + "IW5", + "T5", + "T6", +}; +static_assert(std::extent_v == static_cast(GameId::COUNT)); + class IGame { public: diff --git a/src/Linker/Game/IW3/ZoneCreatorIW3.cpp b/src/Linker/Game/IW3/ZoneCreatorIW3.cpp index 757abfe9..280d32b5 100644 --- a/src/Linker/Game/IW3/ZoneCreatorIW3.cpp +++ b/src/Linker/Game/IW3/ZoneCreatorIW3.cpp @@ -6,23 +6,8 @@ #include "ObjLoading.h" #include "Utils/StringUtils.h" -#include - using namespace IW3; -ZoneCreator::ZoneCreator() -{ - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - { - AddAssetTypeName(assetType, GameAssetPoolIW3::AssetTypeNameByType(assetType)); - } -} - -void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) -{ - m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); -} - std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) { std::vector gdtList; @@ -33,21 +18,10 @@ std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) return gdtList; } -bool ZoneCreator::CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const +void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) { - for (const auto& ignoreEntry : context.m_ignored_assets.m_entries) - { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(ignoreEntry.m_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << ignoreEntry.m_type << "\" for ignore \"" << ignoreEntry.m_name << "\"\n"; - return false; - } - - ignoredAssetMap[ignoreEntry.m_name] = foundAssetTypeEntry->second; - } - - return true; + for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) + loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; } void ZoneCreator::CreateZoneAssetPools(Zone* zone) const @@ -58,12 +32,9 @@ void ZoneCreator::CreateZoneAssetPools(Zone* zone) const zone->m_pools->InitPoolDynamic(assetType); } -bool ZoneCreator::SupportsGame(const std::string& gameName) const +GameId ZoneCreator::GetGameId() const { - auto shortName = g_GameIW3.GetShortName(); - utils::MakeStringLowerCase(shortName); - - return gameName == shortName; + return GameId::IW3; } std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const @@ -80,19 +51,11 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& } const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map)) - return nullptr; + ApplyIgnoredAssets(context, *assetLoadingContext); for (const auto& assetEntry : context.m_definition->m_assets) { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(assetEntry.m_asset_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << assetEntry.m_asset_type << "\"\n"; - return nullptr; - } - - if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name)) + if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) return nullptr; } @@ -100,3 +63,8 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& return zone; } + +asset_type_t ZoneCreator::GetImageAssetType() const +{ + return ASSET_TYPE_IMAGE; +} diff --git a/src/Linker/Game/IW3/ZoneCreatorIW3.h b/src/Linker/Game/IW3/ZoneCreatorIW3.h index 4f259099..7c756cf7 100644 --- a/src/Linker/Game/IW3/ZoneCreatorIW3.h +++ b/src/Linker/Game/IW3/ZoneCreatorIW3.h @@ -1,25 +1,20 @@ #pragma once -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/IZoneCreator.h" -#include -#include +#include "AssetLoading/AssetLoadingContext.h" +#include "Zone/ZoneTypes.h" +#include "ZoneCreation/ZoneCreator.h" namespace IW3 { class ZoneCreator final : public IZoneCreator { - std::unordered_map m_asset_types_by_name; - - void AddAssetTypeName(asset_type_t assetType, std::string name); static std::vector CreateGdtList(const ZoneCreationContext& context); - bool CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const; + static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); void CreateZoneAssetPools(Zone* zone) const; public: - ZoneCreator(); - - _NODISCARD bool SupportsGame(const std::string& gameName) const override; - _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] asset_type_t GetImageAssetType() const override; }; } // namespace IW3 diff --git a/src/Linker/Game/IW4/ZoneCreatorIW4.cpp b/src/Linker/Game/IW4/ZoneCreatorIW4.cpp index 6d105c42..937b9680 100644 --- a/src/Linker/Game/IW4/ZoneCreatorIW4.cpp +++ b/src/Linker/Game/IW4/ZoneCreatorIW4.cpp @@ -5,23 +5,8 @@ #include "ObjLoading.h" #include "Utils/StringUtils.h" -#include - using namespace IW4; -ZoneCreator::ZoneCreator() -{ - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - { - AddAssetTypeName(assetType, GameAssetPoolIW4::AssetTypeNameByType(assetType)); - } -} - -void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) -{ - m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); -} - std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) { std::vector gdtList; @@ -32,21 +17,10 @@ std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) return gdtList; } -bool ZoneCreator::CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const +void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) { - for (const auto& ignoreEntry : context.m_ignored_assets.m_entries) - { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(ignoreEntry.m_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << ignoreEntry.m_type << "\" for ignore \"" << ignoreEntry.m_name << "\"\n"; - return false; - } - - ignoredAssetMap[ignoreEntry.m_name] = foundAssetTypeEntry->second; - } - - return true; + for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) + loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; } void ZoneCreator::CreateZoneAssetPools(Zone* zone) const @@ -57,12 +31,9 @@ void ZoneCreator::CreateZoneAssetPools(Zone* zone) const zone->m_pools->InitPoolDynamic(assetType); } -bool ZoneCreator::SupportsGame(const std::string& gameName) const +GameId ZoneCreator::GetGameId() const { - auto shortName = g_GameIW4.GetShortName(); - utils::MakeStringLowerCase(shortName); - - return gameName == shortName; + return GameId::IW4; } std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const @@ -79,19 +50,11 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& } const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map)) - return nullptr; + ApplyIgnoredAssets(context, *assetLoadingContext); for (const auto& assetEntry : context.m_definition->m_assets) { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(assetEntry.m_asset_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << assetEntry.m_asset_type << "\"\n"; - return nullptr; - } - - if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name)) + if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) return nullptr; } @@ -99,3 +62,8 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& return zone; } + +asset_type_t ZoneCreator::GetImageAssetType() const +{ + return ASSET_TYPE_IMAGE; +} diff --git a/src/Linker/Game/IW4/ZoneCreatorIW4.h b/src/Linker/Game/IW4/ZoneCreatorIW4.h index 27139f68..7523c790 100644 --- a/src/Linker/Game/IW4/ZoneCreatorIW4.h +++ b/src/Linker/Game/IW4/ZoneCreatorIW4.h @@ -1,25 +1,20 @@ #pragma once -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/IZoneCreator.h" -#include -#include +#include "AssetLoading/AssetLoadingContext.h" +#include "Zone/ZoneTypes.h" +#include "ZoneCreation/ZoneCreator.h" namespace IW4 { class ZoneCreator final : public IZoneCreator { - std::unordered_map m_asset_types_by_name; - - void AddAssetTypeName(asset_type_t assetType, std::string name); static std::vector CreateGdtList(const ZoneCreationContext& context); - bool CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const; + static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); void CreateZoneAssetPools(Zone* zone) const; public: - ZoneCreator(); - - _NODISCARD bool SupportsGame(const std::string& gameName) const override; - _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] asset_type_t GetImageAssetType() const override; }; } // namespace IW4 diff --git a/src/Linker/Game/IW5/ZoneCreatorIW5.cpp b/src/Linker/Game/IW5/ZoneCreatorIW5.cpp index c8acd7cc..6f9b913c 100644 --- a/src/Linker/Game/IW5/ZoneCreatorIW5.cpp +++ b/src/Linker/Game/IW5/ZoneCreatorIW5.cpp @@ -5,23 +5,8 @@ #include "ObjLoading.h" #include "Utils/StringUtils.h" -#include - using namespace IW5; -ZoneCreator::ZoneCreator() -{ - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - { - AddAssetTypeName(assetType, GameAssetPoolIW5::AssetTypeNameByType(assetType)); - } -} - -void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) -{ - m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); -} - std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) { std::vector gdtList; @@ -32,21 +17,10 @@ std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) return gdtList; } -bool ZoneCreator::CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const +void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) { - for (const auto& ignoreEntry : context.m_ignored_assets.m_entries) - { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(ignoreEntry.m_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << ignoreEntry.m_type << "\" for ignore \"" << ignoreEntry.m_name << "\"\n"; - return false; - } - - ignoredAssetMap[ignoreEntry.m_name] = foundAssetTypeEntry->second; - } - - return true; + for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) + loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; } void ZoneCreator::CreateZoneAssetPools(Zone* zone) const @@ -57,12 +31,9 @@ void ZoneCreator::CreateZoneAssetPools(Zone* zone) const zone->m_pools->InitPoolDynamic(assetType); } -bool ZoneCreator::SupportsGame(const std::string& gameName) const +GameId ZoneCreator::GetGameId() const { - auto shortName = g_GameIW5.GetShortName(); - utils::MakeStringLowerCase(shortName); - - return gameName == shortName; + return GameId::IW5; } std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const @@ -79,19 +50,11 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& } const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map)) - return nullptr; + ApplyIgnoredAssets(context, *assetLoadingContext); for (const auto& assetEntry : context.m_definition->m_assets) { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(assetEntry.m_asset_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << assetEntry.m_asset_type << "\"\n"; - return nullptr; - } - - if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name)) + if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) return nullptr; } @@ -99,3 +62,8 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& return zone; } + +asset_type_t ZoneCreator::GetImageAssetType() const +{ + return ASSET_TYPE_IMAGE; +} diff --git a/src/Linker/Game/IW5/ZoneCreatorIW5.h b/src/Linker/Game/IW5/ZoneCreatorIW5.h index a018ecf1..cee48755 100644 --- a/src/Linker/Game/IW5/ZoneCreatorIW5.h +++ b/src/Linker/Game/IW5/ZoneCreatorIW5.h @@ -1,25 +1,19 @@ #pragma once +#include "AssetLoading/AssetLoadingContext.h" #include "Zone/ZoneTypes.h" -#include "ZoneCreation/IZoneCreator.h" - -#include -#include +#include "ZoneCreation/ZoneCreator.h" namespace IW5 { class ZoneCreator final : public IZoneCreator { - std::unordered_map m_asset_types_by_name; - - void AddAssetTypeName(asset_type_t assetType, std::string name); static std::vector CreateGdtList(const ZoneCreationContext& context); - bool CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const; + static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); void CreateZoneAssetPools(Zone* zone) const; public: - ZoneCreator(); - - _NODISCARD bool SupportsGame(const std::string& gameName) const override; - _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] asset_type_t GetImageAssetType() const override; }; } // namespace IW5 diff --git a/src/Linker/Game/T5/ZoneCreatorT5.cpp b/src/Linker/Game/T5/ZoneCreatorT5.cpp index 21d71c25..d14e3510 100644 --- a/src/Linker/Game/T5/ZoneCreatorT5.cpp +++ b/src/Linker/Game/T5/ZoneCreatorT5.cpp @@ -6,23 +6,8 @@ #include "ObjLoading.h" #include "Utils/StringUtils.h" -#include - using namespace T5; -ZoneCreator::ZoneCreator() -{ - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - { - AddAssetTypeName(assetType, GameAssetPoolT5::AssetTypeNameByType(assetType)); - } -} - -void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) -{ - m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); -} - std::vector ZoneCreator::CreateGdtList(ZoneCreationContext& context) { std::vector gdtList; @@ -33,21 +18,10 @@ std::vector ZoneCreator::CreateGdtList(ZoneCreationContext& context) return gdtList; } -bool ZoneCreator::CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const +void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) { - for (const auto& ignoreEntry : context.m_ignored_assets.m_entries) - { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(ignoreEntry.m_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << ignoreEntry.m_type << "\" for ignore \"" << ignoreEntry.m_name << "\"\n"; - return false; - } - - ignoredAssetMap[ignoreEntry.m_name] = foundAssetTypeEntry->second; - } - - return true; + for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) + loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; } void ZoneCreator::CreateZoneAssetPools(Zone* zone) const @@ -58,12 +32,9 @@ void ZoneCreator::CreateZoneAssetPools(Zone* zone) const zone->m_pools->InitPoolDynamic(assetType); } -bool ZoneCreator::SupportsGame(const std::string& gameName) const +GameId ZoneCreator::GetGameId() const { - auto shortName = g_GameT5.GetShortName(); - utils::MakeStringLowerCase(shortName); - - return gameName == shortName; + return GameId::T5; } std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const @@ -80,19 +51,11 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& } const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map)) - return nullptr; + ApplyIgnoredAssets(context, *assetLoadingContext); for (const auto& assetEntry : context.m_definition->m_assets) { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(assetEntry.m_asset_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << assetEntry.m_asset_type << "\"\n"; - return nullptr; - } - - if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name)) + if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) return nullptr; } @@ -100,3 +63,8 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& return zone; } + +asset_type_t ZoneCreator::GetImageAssetType() const +{ + return ASSET_TYPE_IMAGE; +} diff --git a/src/Linker/Game/T5/ZoneCreatorT5.h b/src/Linker/Game/T5/ZoneCreatorT5.h index bbc60d3e..a7c8e2e6 100644 --- a/src/Linker/Game/T5/ZoneCreatorT5.h +++ b/src/Linker/Game/T5/ZoneCreatorT5.h @@ -1,25 +1,19 @@ #pragma once +#include "AssetLoading/AssetLoadingContext.h" #include "Zone/ZoneTypes.h" -#include "ZoneCreation/IZoneCreator.h" - -#include -#include +#include "ZoneCreation/ZoneCreator.h" namespace T5 { class ZoneCreator final : public IZoneCreator { - std::unordered_map m_asset_types_by_name; - - void AddAssetTypeName(asset_type_t assetType, std::string name); static std::vector CreateGdtList(ZoneCreationContext& context); - bool CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const; + static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); void CreateZoneAssetPools(Zone* zone) const; public: - ZoneCreator(); - - _NODISCARD bool SupportsGame(const std::string& gameName) const override; - _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] asset_type_t GetImageAssetType() const override; }; } // namespace T5 diff --git a/src/Linker/Game/T6/ZoneCreatorT6.cpp b/src/Linker/Game/T6/ZoneCreatorT6.cpp index 9c0b5687..c50b53fe 100644 --- a/src/Linker/Game/T6/ZoneCreatorT6.cpp +++ b/src/Linker/Game/T6/ZoneCreatorT6.cpp @@ -11,19 +11,6 @@ using namespace T6; -ZoneCreator::ZoneCreator() -{ - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - { - AddAssetTypeName(assetType, GameAssetPoolT6::AssetTypeNameByType(assetType)); - } -} - -void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) -{ - m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); -} - std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) { std::vector gdtList; @@ -34,21 +21,10 @@ std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) return gdtList; } -bool ZoneCreator::CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const +void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) { - for (const auto& ignoreEntry : context.m_ignored_assets.m_entries) - { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(ignoreEntry.m_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << ignoreEntry.m_type << "\" for ignore \"" << ignoreEntry.m_name << "\"\n"; - return false; - } - - ignoredAssetMap[ignoreEntry.m_name] = foundAssetTypeEntry->second; - } - - return true; + for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) + loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; } void ZoneCreator::CreateZoneAssetPools(Zone* zone) const @@ -63,11 +39,11 @@ void ZoneCreator::HandleMetadata(Zone* zone, const ZoneCreationContext& context) { std::vector kvpList; - for (const auto& metaData : context.m_definition->m_metadata) + for (const auto& metaData : context.m_definition->m_properties.m_properties) { - if (metaData->m_key.rfind("level.", 0) == 0) + if (metaData.first.rfind("level.", 0) == 0) { - const std::string strValue = metaData->m_key.substr(std::char_traits::length("level.")); + const std::string strValue = metaData.first.substr(std::char_traits::length("level.")); if (strValue.empty()) continue; @@ -79,7 +55,7 @@ void ZoneCreator::HandleMetadata(Zone* zone, const ZoneCreationContext& context) if (endPtr != &strValue[strValue.size()]) { - std::cout << "Could not parse metadata key \"" << metaData->m_key << "\" as hash\n"; + std::cout << "Could not parse metadata key \"" << metaData.first << "\" as hash\n"; continue; } } @@ -88,7 +64,7 @@ void ZoneCreator::HandleMetadata(Zone* zone, const ZoneCreationContext& context) keyHash = Common::Com_HashKey(strValue.c_str(), 64); } - KeyValuePair kvp{keyHash, Common::Com_HashKey(zone->m_name.c_str(), 64), zone->GetMemory()->Dup(metaData->m_value.c_str())}; + KeyValuePair kvp{keyHash, Common::Com_HashKey(zone->m_name.c_str(), 64), zone->GetMemory()->Dup(metaData.second.c_str())}; kvpList.push_back(kvp); } } @@ -107,12 +83,9 @@ void ZoneCreator::HandleMetadata(Zone* zone, const ZoneCreationContext& context) } } -bool ZoneCreator::SupportsGame(const std::string& gameName) const +GameId ZoneCreator::GetGameId() const { - auto shortName = g_GameT6.GetShortName(); - utils::MakeStringLowerCase(shortName); - - return gameName == shortName; + return GameId::T6; } std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const @@ -129,21 +102,13 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& } const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map)) - return nullptr; + ApplyIgnoredAssets(context, *assetLoadingContext); HandleMetadata(zone.get(), context); for (const auto& assetEntry : context.m_definition->m_assets) { - const auto foundAssetTypeEntry = m_asset_types_by_name.find(assetEntry.m_asset_type); - if (foundAssetTypeEntry == m_asset_types_by_name.end()) - { - std::cout << "Unknown asset type \"" << assetEntry.m_asset_type << "\"\n"; - return nullptr; - } - - if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name)) + if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) return nullptr; } @@ -151,3 +116,8 @@ std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& return zone; } + +asset_type_t ZoneCreator::GetImageAssetType() const +{ + return ASSET_TYPE_IMAGE; +} diff --git a/src/Linker/Game/T6/ZoneCreatorT6.h b/src/Linker/Game/T6/ZoneCreatorT6.h index 20028d60..17e24c78 100644 --- a/src/Linker/Game/T6/ZoneCreatorT6.h +++ b/src/Linker/Game/T6/ZoneCreatorT6.h @@ -1,26 +1,20 @@ #pragma once +#include "AssetLoading/AssetLoadingContext.h" #include "Zone/ZoneTypes.h" -#include "ZoneCreation/IZoneCreator.h" - -#include -#include +#include "ZoneCreation/ZoneCreator.h" namespace T6 { class ZoneCreator final : public IZoneCreator { - std::unordered_map m_asset_types_by_name; - - void AddAssetTypeName(asset_type_t assetType, std::string name); static std::vector CreateGdtList(const ZoneCreationContext& context); - bool CreateIgnoredAssetMap(const ZoneCreationContext& context, std::unordered_map& ignoredAssetMap) const; + static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); void CreateZoneAssetPools(Zone* zone) const; void HandleMetadata(Zone* zone, const ZoneCreationContext& context) const; public: - ZoneCreator(); - - _NODISCARD bool SupportsGame(const std::string& gameName) const override; - _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; + [[nodiscard]] asset_type_t GetImageAssetType() const override; }; } // namespace T6 diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index 8428de7a..1622e89d 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -1,10 +1,5 @@ #include "Linker.h" -#include "Game/IW3/ZoneCreatorIW3.h" -#include "Game/IW4/ZoneCreatorIW4.h" -#include "Game/IW5/ZoneCreatorIW5.h" -#include "Game/T5/ZoneCreatorT5.h" -#include "Game/T6/ZoneCreatorT6.h" #include "LinkerArgs.h" #include "LinkerSearchPaths.h" #include "ObjContainer/IPak/IPakWriter.h" @@ -13,15 +8,12 @@ #include "ObjLoading.h" #include "ObjWriting.h" #include "SearchPath/SearchPaths.h" -#include "Utils/Arguments/ArgumentParser.h" -#include "Utils/ClassUtils.h" #include "Utils/ObjFileStream.h" -#include "Utils/StringUtils.h" #include "Zone/AssetList/AssetList.h" #include "Zone/AssetList/AssetListStream.h" #include "Zone/Definition/ZoneDefinitionStream.h" -#include "ZoneCreation/IZoneCreator.h" #include "ZoneCreation/ZoneCreationContext.h" +#include "ZoneCreation/ZoneCreator.h" #include "ZoneLoading.h" #include "ZoneWriting.h" @@ -29,41 +21,12 @@ #include #include #include -#include #include namespace fs = std::filesystem; -const IZoneCreator* const ZONE_CREATORS[]{ - new IW3::ZoneCreator(), - new IW4::ZoneCreator(), - new IW5::ZoneCreator(), - new T5::ZoneCreator(), - new T6::ZoneCreator(), -}; - -enum class ProjectType -{ - NONE, - FASTFILE, - IPAK, - - MAX -}; - -constexpr const char* PROJECT_TYPE_NAMES[static_cast(ProjectType::MAX)]{ - "none", - "fastfile", - "ipak", -}; - class LinkerImpl final : public Linker { - static constexpr auto METADATA_GAME = "game"; - static constexpr auto METADATA_GDT = "gdt"; - static constexpr auto METADATA_NAME = "name"; - static constexpr auto METADATA_TYPE = "type"; - LinkerArgs m_args; LinkerSearchPaths m_search_paths; std::vector> m_loaded_zones; @@ -96,6 +59,7 @@ class LinkerImpl final : public Linker } ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, definitionFileName, m_args.m_verbose); + zoneDefinitionInputStream.SetPreviouslySetGame(zoneDefinition.m_game); includeDefinition = zoneDefinitionInputStream.ReadDefinition(); } @@ -117,7 +81,7 @@ class LinkerImpl final : public Linker return true; } - bool ReadAssetList(const std::string& zoneName, AssetList& assetList, ISearchPath* sourceSearchPath) const + bool ReadAssetList(const std::string& zoneName, const GameId game, AssetList& assetList, ISearchPath* sourceSearchPath) const { { const auto assetListFileName = std::format("assetlist/{}.csv", zoneName); @@ -125,14 +89,16 @@ class LinkerImpl final : public Linker if (assetListStream.IsOpen()) { - const AssetListInputStream stream(*assetListStream.m_stream); + const AssetListInputStream stream(*assetListStream.m_stream, game); AssetListEntry entry; - while (stream.NextEntry(entry)) + bool failure; + while (stream.NextEntry(entry, &failure)) { assetList.m_entries.emplace_back(std::move(entry)); } - return true; + + return !failure; } } @@ -157,7 +123,7 @@ class LinkerImpl final : public Linker for (const auto& assetListName : zoneDefinition.m_asset_lists) { AssetList assetList; - if (!ReadAssetList(assetListName, assetList, sourceSearchPath)) + if (!ReadAssetList(assetListName, zoneDefinition.m_game, assetList, sourceSearchPath)) { std::cerr << std::format("Failed to read asset list \"{}\"\n", assetListName); return false; @@ -169,33 +135,6 @@ class LinkerImpl final : public Linker return true; } - static bool GetNameFromZoneDefinition(std::string& name, const std::string& targetName, const ZoneDefinition& zoneDefinition) - { - auto firstNameEntry = true; - const auto [rangeBegin, rangeEnd] = zoneDefinition.m_metadata_lookup.equal_range(METADATA_NAME); - for (auto i = rangeBegin; i != rangeEnd; ++i) - { - if (firstNameEntry) - { - name = i->second->m_value; - firstNameEntry = false; - } - else - { - if (name != i->second->m_value) - { - std::cerr << std::format("Conflicting names in target \"{}\": {} != {}\n", targetName, name, i->second->m_value); - return false; - } - } - } - - if (firstNameEntry) - name = targetName; - - return true; - } - std::unique_ptr ReadZoneDefinition(const std::string& targetName, ISearchPath* sourceSearchPath) const { std::unique_ptr zoneDefinition; @@ -218,9 +157,6 @@ class LinkerImpl final : public Linker return nullptr; } - if (!GetNameFromZoneDefinition(zoneDefinition->m_name, targetName, *zoneDefinition)) - return nullptr; - if (!IncludeAdditionalZoneDefinitions(targetName, *zoneDefinition, sourceSearchPath)) return nullptr; @@ -235,19 +171,13 @@ class LinkerImpl final : public Linker if (context.m_definition->m_ignores.empty()) return true; - std::map> zoneDefinitionAssetsByName; - for (auto& entry : context.m_definition->m_assets) - { - zoneDefinitionAssetsByName.try_emplace(entry.m_asset_name, entry); - } - for (const auto& ignore : context.m_definition->m_ignores) { if (ignore == targetName) continue; std::vector assetList; - if (!ReadAssetList(ignore, context.m_ignored_assets, sourceSearchPath)) + if (!ReadAssetList(ignore, context.m_definition->m_game, context.m_ignored_assets, sourceSearchPath)) { std::cerr << std::format("Failed to read asset listing for ignoring assets of project \"{}\".\n", ignore); return false; @@ -256,101 +186,14 @@ class LinkerImpl final : public Linker return true; } - static bool ProjectTypeByName(ProjectType& projectType, const std::string& projectTypeName) - { - for (auto i = 0u; i < static_cast(ProjectType::MAX); i++) - { - if (projectTypeName == PROJECT_TYPE_NAMES[i]) - { - projectType = static_cast(i); - return true; - } - } - - return false; - } - - static bool GetProjectTypeFromZoneDefinition(ProjectType& projectType, const std::string& targetName, const ZoneDefinition& zoneDefinition) - { - auto firstTypeEntry = true; - const auto [rangeBegin, rangeEnd] = zoneDefinition.m_metadata_lookup.equal_range(METADATA_TYPE); - for (auto i = rangeBegin; i != rangeEnd; ++i) - { - ProjectType parsedProjectType; - if (!ProjectTypeByName(parsedProjectType, i->second->m_value)) - { - std::cerr << std::format("Not a valid project type: \"{}\"\n", i->second->m_value); - return false; - } - - if (firstTypeEntry) - { - projectType = parsedProjectType; - firstTypeEntry = false; - } - else - { - if (projectType != parsedProjectType) - { - std::cerr << std::format("Conflicting types in target \"{}\": {} != {}\n", - targetName, - PROJECT_TYPE_NAMES[static_cast(projectType)], - PROJECT_TYPE_NAMES[static_cast(parsedProjectType)]); - return false; - } - } - } - - if (firstTypeEntry) - { - if (zoneDefinition.m_assets.empty()) - projectType = ProjectType::NONE; - else - projectType = ProjectType::FASTFILE; - } - - return true; - } - - static bool GetGameNameFromZoneDefinition(std::string& gameName, const std::string& targetName, const ZoneDefinition& zoneDefinition) - { - auto firstGameEntry = true; - const auto [rangeBegin, rangeEnd] = zoneDefinition.m_metadata_lookup.equal_range(METADATA_GAME); - for (auto i = rangeBegin; i != rangeEnd; ++i) - { - if (firstGameEntry) - { - gameName = i->second->m_value; - firstGameEntry = false; - } - else - { - if (gameName != i->second->m_value) - { - std::cerr << std::format("Conflicting game names in target \"{}\": {} != {}\n", targetName, gameName, i->second->m_value); - return false; - } - } - } - - if (firstGameEntry) - { - std::cerr << std::format("No game name was specified for target \"{}\"\n", targetName); - return false; - } - - return true; - } - static bool LoadGdtFilesFromZoneDefinition(std::vector>& gdtList, const ZoneDefinition& zoneDefinition, ISearchPath* gdtSearchPath) { - const auto [rangeBegin, rangeEnd] = zoneDefinition.m_metadata_lookup.equal_range(METADATA_GDT); - for (auto i = rangeBegin; i != rangeEnd; ++i) + for (const auto& gdtName : zoneDefinition.m_gdts) { - const auto gdtFile = gdtSearchPath->Open(i->second->m_value + ".gdt"); + const auto gdtFile = gdtSearchPath->Open(std::format("{}.gdt", gdtName)); if (!gdtFile.IsOpen()) { - std::cerr << std::format("Failed to open file for gdt \"{}\"\n", i->second->m_value); + std::cerr << std::format("Failed to open file for gdt \"{}\"\n", gdtName); return false; } @@ -358,7 +201,7 @@ class LinkerImpl final : public Linker auto gdt = std::make_unique(); if (!gdtReader.Read(*gdt)) { - std::cerr << std::format("Failed to read gdt file \"{}\"\n", i->second->m_value); + std::cerr << std::format("Failed to read gdt file \"{}\"\n", gdtName); return false; } @@ -374,23 +217,14 @@ class LinkerImpl final : public Linker ISearchPath* gdtSearchPath, ISearchPath* sourceSearchPath) const { - const auto context = std::make_unique(assetSearchPath, &zoneDefinition); + const auto context = std::make_unique(&zoneDefinition, assetSearchPath); if (!ProcessZoneDefinitionIgnores(targetName, *context, sourceSearchPath)) return nullptr; - if (!GetGameNameFromZoneDefinition(context->m_game_name, targetName, zoneDefinition)) - return nullptr; - utils::MakeStringLowerCase(context->m_game_name); if (!LoadGdtFilesFromZoneDefinition(context->m_gdt_files, zoneDefinition, gdtSearchPath)) return nullptr; - for (const auto* zoneCreator : ZONE_CREATORS) - { - if (zoneCreator->SupportsGame(context->m_game_name)) - return zoneCreator->CreateZoneForDefinition(*context); - } - - std::cerr << std::format("Unsupported game: {}\n", context->m_game_name); - return nullptr; + const auto* creator = IZoneCreator::GetCreatorForGame(zoneDefinition.m_game); + return creator->CreateZoneForDefinition(*context); } bool WriteZoneToFile(const std::string& projectName, Zone* zone) const @@ -444,7 +278,7 @@ class LinkerImpl final : public Linker { const fs::path ipakFolderPath(m_args.GetOutputFolderPathForProject(projectName)); auto ipakFilePath(ipakFolderPath); - ipakFilePath.append(zoneDefinition.m_name + ".ipak"); + ipakFilePath.append(std::format("{}.ipak", zoneDefinition.m_name)); fs::create_directories(ipakFolderPath); @@ -453,12 +287,13 @@ class LinkerImpl final : public Linker return false; const auto ipakWriter = IPakWriter::Create(stream, &assetSearchPaths); + const auto imageAssetType = IZoneCreator::GetCreatorForGame(zoneDefinition.m_game)->GetImageAssetType(); for (const auto& assetEntry : zoneDefinition.m_assets) { if (assetEntry.m_is_reference) continue; - if (assetEntry.m_asset_type == "image") + if (assetEntry.m_asset_type == imageAssetType) ipakWriter->AddImage(assetEntry.m_asset_name); } @@ -499,22 +334,14 @@ class LinkerImpl final : public Linker if (!zoneDefinition) return false; - ProjectType projectType; - if (!GetProjectTypeFromZoneDefinition(projectType, targetName, *zoneDefinition)) - return false; - auto result = true; - if (projectType != ProjectType::NONE) + if (zoneDefinition->m_type != ProjectType::NONE) { - std::string gameName; - if (!GetGameNameFromZoneDefinition(gameName, targetName, *zoneDefinition)) - return false; - utils::MakeStringLowerCase(gameName); - + const auto& gameName = GameId_Names[static_cast(zoneDefinition->m_game)]; auto assetSearchPaths = m_search_paths.GetAssetSearchPathsForProject(gameName, projectName); auto gdtSearchPaths = m_search_paths.GetGdtSearchPathsForProject(gameName, projectName); - switch (projectType) + switch (zoneDefinition->m_type) { case ProjectType::FASTFILE: result = BuildFastFile(projectName, targetName, *zoneDefinition, assetSearchPaths, gdtSearchPaths, sourceSearchPaths); diff --git a/src/Linker/ZoneCreation/ZoneCreationContext.cpp b/src/Linker/ZoneCreation/ZoneCreationContext.cpp index 48181694..55b45501 100644 --- a/src/Linker/ZoneCreation/ZoneCreationContext.cpp +++ b/src/Linker/ZoneCreation/ZoneCreationContext.cpp @@ -1,13 +1,13 @@ #include "ZoneCreationContext.h" ZoneCreationContext::ZoneCreationContext() - : m_asset_search_path(nullptr), - m_definition(nullptr) + : m_definition(nullptr), + m_asset_search_path(nullptr) { } -ZoneCreationContext::ZoneCreationContext(ISearchPath* assetSearchPath, ZoneDefinition* definition) - : m_asset_search_path(assetSearchPath), - m_definition(definition) +ZoneCreationContext::ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath) + : m_definition(definition), + m_asset_search_path(assetSearchPath) { } diff --git a/src/Linker/ZoneCreation/ZoneCreationContext.h b/src/Linker/ZoneCreation/ZoneCreationContext.h index efccbdb7..3c8a098c 100644 --- a/src/Linker/ZoneCreation/ZoneCreationContext.h +++ b/src/Linker/ZoneCreation/ZoneCreationContext.h @@ -5,18 +5,16 @@ #include "Zone/Definition/ZoneDefinition.h" #include -#include #include class ZoneCreationContext { public: - std::string m_game_name; - ISearchPath* m_asset_search_path; ZoneDefinition* m_definition; + ISearchPath* m_asset_search_path; std::vector> m_gdt_files; AssetList m_ignored_assets; ZoneCreationContext(); - ZoneCreationContext(ISearchPath* assetSearchPath, ZoneDefinition* definition); + ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath); }; diff --git a/src/Linker/ZoneCreation/ZoneCreator.cpp b/src/Linker/ZoneCreation/ZoneCreator.cpp new file mode 100644 index 00000000..7d8b4958 --- /dev/null +++ b/src/Linker/ZoneCreation/ZoneCreator.cpp @@ -0,0 +1,26 @@ +#include "ZoneCreator.h" + +#include "Game/IW3/ZoneCreatorIW3.h" +#include "Game/IW4/ZoneCreatorIW4.h" +#include "Game/IW5/ZoneCreatorIW5.h" +#include "Game/T5/ZoneCreatorT5.h" +#include "Game/T6/ZoneCreatorT6.h" + +#include + +const IZoneCreator* IZoneCreator::GetCreatorForGame(GameId game) +{ + static const IZoneCreator* zoneCreators[static_cast(GameId::COUNT)]{ + new IW3::ZoneCreator(), + new IW4::ZoneCreator(), + new IW5::ZoneCreator(), + new T5::ZoneCreator(), + new T6::ZoneCreator(), + }; + + assert(static_cast(game) < static_cast(GameId::COUNT)); + const auto* result = zoneCreators[static_cast(game)]; + assert(result); + + return result; +} diff --git a/src/Linker/ZoneCreation/IZoneCreator.h b/src/Linker/ZoneCreation/ZoneCreator.h similarity index 58% rename from src/Linker/ZoneCreation/IZoneCreator.h rename to src/Linker/ZoneCreation/ZoneCreator.h index 974361e5..470c595d 100644 --- a/src/Linker/ZoneCreation/IZoneCreator.h +++ b/src/Linker/ZoneCreation/ZoneCreator.h @@ -1,10 +1,8 @@ #pragma once -#include "Utils/ClassUtils.h" + #include "Zone/Zone.h" #include "ZoneCreationContext.h" -#include - class IZoneCreator { public: @@ -15,6 +13,9 @@ public: IZoneCreator& operator=(const IZoneCreator& other) = default; IZoneCreator& operator=(IZoneCreator&& other) noexcept = default; - _NODISCARD virtual bool SupportsGame(const std::string& gameName) const = 0; - _NODISCARD virtual std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const = 0; + [[nodiscard]] virtual GameId GetGameId() const = 0; + [[nodiscard]] virtual std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const = 0; + [[nodiscard]] virtual asset_type_t GetImageAssetType() const = 0; + + static const IZoneCreator* GetCreatorForGame(GameId game); }; diff --git a/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp b/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp index c7a97a3d..b3d0b492 100644 --- a/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp +++ b/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp @@ -31,7 +31,7 @@ XAssetInfoGeneric* AssetLoadingManager::AddAssetInternal(std::unique_ptrAddAsset(std::move(xAssetInfo)); if (m_last_dependency_loaded == nullptr) - std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType), pAssetName); + std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType), pAssetName); return m_last_dependency_loaded; } @@ -66,7 +66,7 @@ XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t return lastDependency; } - std::cerr << std::format("Failed to create empty asset \"{}\" for type \"{}\"\n", assetName, m_context.m_zone.m_pools->GetAssetTypeName(assetType)); + std::cerr << std::format("Failed to create empty asset \"{}\" for type \"{}\"\n", assetName, *m_context.m_zone.m_pools->GetAssetTypeName(assetType)); return nullptr; } @@ -126,7 +126,7 @@ XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t a return lastDependency; } - std::cerr << std::format("Failed to load asset of type \"{}\": \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType), assetName); + std::cerr << std::format("Failed to load asset of type \"{}\": \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType), assetName); return nullptr; } @@ -150,7 +150,7 @@ XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetT return LoadAssetDependency(assetType, assetName, loader->second.get()); } - std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType)); + std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType)); return nullptr; } @@ -171,6 +171,6 @@ IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const ass return IndirectAssetReference(assetType, assetName); } - std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType)); + std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType)); return IndirectAssetReference(assetType, assetName); } diff --git a/src/Unlinker/ContentLister/ContentPrinter.cpp b/src/Unlinker/ContentLister/ContentPrinter.cpp index 54c707dd..612940db 100644 --- a/src/Unlinker/ContentLister/ContentPrinter.cpp +++ b/src/Unlinker/ContentLister/ContentPrinter.cpp @@ -1,5 +1,8 @@ #include "ContentPrinter.h" +#include +#include + ContentPrinter::ContentPrinter(Zone* zone) { m_zone = zone; @@ -8,13 +11,11 @@ ContentPrinter::ContentPrinter(Zone* zone) void ContentPrinter::PrintContent() const { const auto* pools = m_zone->m_pools.get(); - printf("Zone '%s' (%s)\n", m_zone->m_name.c_str(), m_zone->m_game->GetShortName().c_str()); - puts("Content:"); + std::cout << std::format("Zone '{}' ({})\n", m_zone->m_name, m_zone->m_game->GetShortName()); + std::cout << "Content:\n"; for (const auto& asset : *pools) - { - printf("%s, %s\n", pools->GetAssetTypeName(asset->m_type), asset->m_name.c_str()); - } + std::cout << std::format("{}, {}\n", *pools->GetAssetTypeName(asset->m_type), asset->m_name); - puts(""); + std::cout << "\n"; } diff --git a/src/Unlinker/Game/IW3/ZoneDefWriterIW3.cpp b/src/Unlinker/Game/IW3/ZoneDefWriterIW3.cpp index 7e1dce97..bde21a42 100644 --- a/src/Unlinker/Game/IW3/ZoneDefWriterIW3.cpp +++ b/src/Unlinker/Game/IW3/ZoneDefWriterIW3.cpp @@ -25,7 +25,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin // Localized strings are all collected in one string file. So only add this to the zone file. if (!pools->m_localize->m_asset_lookup.empty()) { - stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); } for (const auto& asset : *pools) @@ -36,7 +36,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin break; default: - stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(asset->m_type), asset->m_name); break; } } diff --git a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp index 869e70ff..f9de09bb 100644 --- a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp +++ b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp @@ -25,7 +25,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin // Localized strings are all collected in one string file. So only add this to the zone file. if (!pools->m_localize->m_asset_lookup.empty()) { - stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); } for (const auto& asset : *pools) @@ -36,7 +36,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin break; default: - stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(asset->m_type), asset->m_name); break; } } diff --git a/src/Unlinker/Game/IW5/ZoneDefWriterIW5.cpp b/src/Unlinker/Game/IW5/ZoneDefWriterIW5.cpp index cd2e9b3d..1de38c5e 100644 --- a/src/Unlinker/Game/IW5/ZoneDefWriterIW5.cpp +++ b/src/Unlinker/Game/IW5/ZoneDefWriterIW5.cpp @@ -25,7 +25,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin // Localized strings are all collected in one string file. So only add this to the zone file. if (!pools->m_localize->m_asset_lookup.empty()) { - stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); } for (const auto& asset : *pools) @@ -36,7 +36,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin break; default: - stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(asset->m_type), asset->m_name); break; } } diff --git a/src/Unlinker/Game/T5/ZoneDefWriterT5.cpp b/src/Unlinker/Game/T5/ZoneDefWriterT5.cpp index 024578bb..c875c6ba 100644 --- a/src/Unlinker/Game/T5/ZoneDefWriterT5.cpp +++ b/src/Unlinker/Game/T5/ZoneDefWriterT5.cpp @@ -25,7 +25,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin // Localized strings are all collected in one string file. So only add this to the zone file. if (!pools->m_localize->m_asset_lookup.empty()) { - stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); } for (const auto& asset : *pools) @@ -36,7 +36,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin break; default: - stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(asset->m_type), asset->m_name); break; } } diff --git a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp index 6534636d..cada1f6a 100644 --- a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp +++ b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp @@ -83,7 +83,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin // Localized strings are all collected in one string file. So only add this to the zone file. if (!pools->m_localize->m_asset_lookup.empty()) { - stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name); } for (const auto& asset : *pools) @@ -95,7 +95,7 @@ void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, const Unlin break; default: - stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + stream.WriteEntry(*pools->GetAssetTypeName(asset->m_type), asset->m_name); break; } } diff --git a/src/Unlinker/Unlinker.cpp b/src/Unlinker/Unlinker.cpp index 284bad9f..8dae19b9 100644 --- a/src/Unlinker/Unlinker.cpp +++ b/src/Unlinker/Unlinker.cpp @@ -226,7 +226,7 @@ private: std::vector handledSpecifiedAssets(m_args.m_specified_asset_types.size()); for (auto i = 0; i < assetTypeCount; i++) { - const auto assetTypeName = std::string(context.m_zone->m_pools->GetAssetTypeName(i)); + const auto assetTypeName = std::string(*context.m_zone->m_pools->GetAssetTypeName(i)); const auto foundSpecifiedEntry = m_args.m_specified_asset_type_map.find(assetTypeName); if (foundSpecifiedEntry != m_args.m_specified_asset_type_map.end()) @@ -256,7 +256,7 @@ private: auto first = true; for (auto i = 0; i < assetTypeCount; i++) { - const auto assetTypeName = std::string(context.m_zone->m_pools->GetAssetTypeName(i)); + const auto assetTypeName = std::string(*context.m_zone->m_pools->GetAssetTypeName(i)); if (first) first = false; diff --git a/src/ZoneCommon/Game/IW3/AssetNameResolverIW3.cpp b/src/ZoneCommon/Game/IW3/AssetNameResolverIW3.cpp new file mode 100644 index 00000000..11284cff --- /dev/null +++ b/src/ZoneCommon/Game/IW3/AssetNameResolverIW3.cpp @@ -0,0 +1,22 @@ +#include "AssetNameResolverIW3.h" + +#include "Game/IW3/GameAssetPoolIW3.h" +#include "Utils/StringUtils.h" + +using namespace IW3; + +AssetNameResolver::AssetNameResolver() +{ + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + AddAssetTypeName(assetType, *GameAssetPoolIW3::AssetTypeNameByType(assetType)); +} + +GameId AssetNameResolver::GetGameId() const +{ + return GameId::IW3; +} + +std::optional AssetNameResolver::GetAssetTypeName(const asset_type_t assetType) const +{ + return GameAssetPoolIW3::AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/IW3/AssetNameResolverIW3.h b/src/ZoneCommon/Game/IW3/AssetNameResolverIW3.h new file mode 100644 index 00000000..fa7bffb4 --- /dev/null +++ b/src/ZoneCommon/Game/IW3/AssetNameResolverIW3.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Zone/AssetNameResolver.h" + +namespace IW3 +{ + class AssetNameResolver final : public HashMapBasedAssetNameResolver + { + public: + AssetNameResolver(); + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::optional GetAssetTypeName(asset_type_t assetType) const override; + }; +} // namespace IW3 diff --git a/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.cpp b/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.cpp index 998e3166..0642b073 100644 --- a/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.cpp +++ b/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.cpp @@ -218,15 +218,15 @@ XAssetInfoGeneric* GameAssetPoolIW3::GetAsset(const asset_type_t type, const std #undef CASE_GET_ASSET } -const char* GameAssetPoolIW3::AssetTypeNameByType(const asset_type_t assetType) +std::optional GameAssetPoolIW3::AssetTypeNameByType(const asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent_v)) return ASSET_TYPE_NAMES[assetType]; - return ASSET_TYPE_INVALID; + return std::nullopt; } -const char* GameAssetPoolIW3::GetAssetTypeName(const asset_type_t assetType) const +std::optional GameAssetPoolIW3::GetAssetTypeName(const asset_type_t assetType) const { return AssetTypeNameByType(assetType); } diff --git a/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.h b/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.h index 8a27de8e..062c7af2 100644 --- a/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.h +++ b/src/ZoneCommon/Game/IW3/GameAssetPoolIW3.h @@ -5,12 +5,12 @@ #include "Pool/ZoneAssetPools.h" #include +#include class GameAssetPoolIW3 final : public ZoneAssetPools { int m_priority; - static constexpr const char* ASSET_TYPE_INVALID = "invalid_asset_type"; static const char* ASSET_TYPE_NAMES[]; protected: @@ -54,8 +54,8 @@ public: _NODISCARD XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const override; - static const char* AssetTypeNameByType(asset_type_t assetType); - _NODISCARD const char* GetAssetTypeName(asset_type_t assetType) const override; + static std::optional AssetTypeNameByType(asset_type_t assetType); + _NODISCARD std::optional GetAssetTypeName(asset_type_t assetType) const override; static asset_type_t AssetTypeCount(); _NODISCARD asset_type_t GetAssetTypeCount() const override; diff --git a/src/ZoneCommon/Game/IW4/AssetNameResolverIW4.cpp b/src/ZoneCommon/Game/IW4/AssetNameResolverIW4.cpp new file mode 100644 index 00000000..1ca578fd --- /dev/null +++ b/src/ZoneCommon/Game/IW4/AssetNameResolverIW4.cpp @@ -0,0 +1,22 @@ +#include "AssetNameResolverIW4.h" + +#include "Game/IW4/GameAssetPoolIW4.h" +#include "Utils/StringUtils.h" + +using namespace IW4; + +AssetNameResolver::AssetNameResolver() +{ + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + AddAssetTypeName(assetType, *GameAssetPoolIW4::AssetTypeNameByType(assetType)); +} + +GameId AssetNameResolver::GetGameId() const +{ + return GameId::IW4; +} + +std::optional AssetNameResolver::GetAssetTypeName(const asset_type_t assetType) const +{ + return GameAssetPoolIW4::AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/IW4/AssetNameResolverIW4.h b/src/ZoneCommon/Game/IW4/AssetNameResolverIW4.h new file mode 100644 index 00000000..49188830 --- /dev/null +++ b/src/ZoneCommon/Game/IW4/AssetNameResolverIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Zone/AssetNameResolver.h" + +namespace IW4 +{ + class AssetNameResolver final : public HashMapBasedAssetNameResolver + { + public: + AssetNameResolver(); + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::optional GetAssetTypeName(asset_type_t assetType) const override; + }; +} // namespace IW4 diff --git a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp index 6e6585fd..c0d38a56 100644 --- a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp +++ b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp @@ -259,15 +259,15 @@ XAssetInfoGeneric* GameAssetPoolIW4::GetAsset(const asset_type_t type, const std #undef CASE_GET_ASSET } -const char* GameAssetPoolIW4::AssetTypeNameByType(const asset_type_t assetType) +std::optional GameAssetPoolIW4::AssetTypeNameByType(const asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent_v)) return ASSET_TYPE_NAMES[assetType]; - return ASSET_TYPE_INVALID; + return std::nullopt; } -const char* GameAssetPoolIW4::GetAssetTypeName(const asset_type_t assetType) const +std::optional GameAssetPoolIW4::GetAssetTypeName(const asset_type_t assetType) const { return AssetTypeNameByType(assetType); } diff --git a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h index bb0fc12c..7cb4079c 100644 --- a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h +++ b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h @@ -62,8 +62,8 @@ public: _NODISCARD XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const override; - static const char* AssetTypeNameByType(asset_type_t assetType); - _NODISCARD const char* GetAssetTypeName(asset_type_t assetType) const override; + static std::optional AssetTypeNameByType(asset_type_t assetType); + _NODISCARD std::optional GetAssetTypeName(asset_type_t assetType) const override; static asset_type_t AssetTypeCount(); _NODISCARD asset_type_t GetAssetTypeCount() const override; diff --git a/src/ZoneCommon/Game/IW5/AssetNameResolverIW5.cpp b/src/ZoneCommon/Game/IW5/AssetNameResolverIW5.cpp new file mode 100644 index 00000000..f25c5e77 --- /dev/null +++ b/src/ZoneCommon/Game/IW5/AssetNameResolverIW5.cpp @@ -0,0 +1,22 @@ +#include "AssetNameResolverIW5.h" + +#include "Game/IW5/GameAssetPoolIW5.h" +#include "Utils/StringUtils.h" + +using namespace IW5; + +AssetNameResolver::AssetNameResolver() +{ + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + AddAssetTypeName(assetType, *GameAssetPoolIW5::AssetTypeNameByType(assetType)); +} + +GameId AssetNameResolver::GetGameId() const +{ + return GameId::IW5; +} + +std::optional AssetNameResolver::GetAssetTypeName(const asset_type_t assetType) const +{ + return GameAssetPoolIW5::AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/IW5/AssetNameResolverIW5.h b/src/ZoneCommon/Game/IW5/AssetNameResolverIW5.h new file mode 100644 index 00000000..15096e8a --- /dev/null +++ b/src/ZoneCommon/Game/IW5/AssetNameResolverIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Zone/AssetNameResolver.h" + +namespace IW5 +{ + class AssetNameResolver final : public HashMapBasedAssetNameResolver + { + public: + AssetNameResolver(); + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::optional GetAssetTypeName(asset_type_t assetType) const override; + }; +} // namespace IW5 diff --git a/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.cpp b/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.cpp index e928fad7..87ff0f5e 100644 --- a/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.cpp +++ b/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.cpp @@ -316,15 +316,15 @@ XAssetInfoGeneric* GameAssetPoolIW5::GetAsset(const asset_type_t type, const std #undef CASE_GET_ASSET } -const char* GameAssetPoolIW5::AssetTypeNameByType(const asset_type_t assetType) +std::optional GameAssetPoolIW5::AssetTypeNameByType(const asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent_v)) return ASSET_TYPE_NAMES[assetType]; - return ASSET_TYPE_INVALID; + return std::nullopt; } -const char* GameAssetPoolIW5::GetAssetTypeName(const asset_type_t assetType) const +std::optional GameAssetPoolIW5::GetAssetTypeName(const asset_type_t assetType) const { return AssetTypeNameByType(assetType); } diff --git a/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.h b/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.h index 49cf0456..a12f4df4 100644 --- a/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.h +++ b/src/ZoneCommon/Game/IW5/GameAssetPoolIW5.h @@ -66,8 +66,8 @@ public: _NODISCARD XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const override; - static const char* AssetTypeNameByType(asset_type_t assetType); - _NODISCARD const char* GetAssetTypeName(asset_type_t assetType) const override; + static std::optional AssetTypeNameByType(asset_type_t assetType); + _NODISCARD std::optional GetAssetTypeName(asset_type_t assetType) const override; static asset_type_t AssetTypeCount(); _NODISCARD asset_type_t GetAssetTypeCount() const override; diff --git a/src/ZoneCommon/Game/T5/AssetNameResolverT5.cpp b/src/ZoneCommon/Game/T5/AssetNameResolverT5.cpp new file mode 100644 index 00000000..58b10166 --- /dev/null +++ b/src/ZoneCommon/Game/T5/AssetNameResolverT5.cpp @@ -0,0 +1,22 @@ +#include "AssetNameResolverT5.h" + +#include "Game/T5/GameAssetPoolT5.h" +#include "Utils/StringUtils.h" + +using namespace T5; + +AssetNameResolver::AssetNameResolver() +{ + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + AddAssetTypeName(assetType, *GameAssetPoolT5::AssetTypeNameByType(assetType)); +} + +GameId AssetNameResolver::GetGameId() const +{ + return GameId::T5; +} + +std::optional AssetNameResolver::GetAssetTypeName(const asset_type_t assetType) const +{ + return GameAssetPoolT5::AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/T5/AssetNameResolverT5.h b/src/ZoneCommon/Game/T5/AssetNameResolverT5.h new file mode 100644 index 00000000..30de16a5 --- /dev/null +++ b/src/ZoneCommon/Game/T5/AssetNameResolverT5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Zone/AssetNameResolver.h" + +namespace T5 +{ + class AssetNameResolver final : public HashMapBasedAssetNameResolver + { + public: + AssetNameResolver(); + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::optional GetAssetTypeName(asset_type_t assetType) const override; + }; +} // namespace T5 diff --git a/src/ZoneCommon/Game/T5/GameAssetPoolT5.cpp b/src/ZoneCommon/Game/T5/GameAssetPoolT5.cpp index c1facfde..097412ec 100644 --- a/src/ZoneCommon/Game/T5/GameAssetPoolT5.cpp +++ b/src/ZoneCommon/Game/T5/GameAssetPoolT5.cpp @@ -249,15 +249,15 @@ XAssetInfoGeneric* GameAssetPoolT5::GetAsset(const asset_type_t type, const std: #undef CASE_GET_ASSET } -const char* GameAssetPoolT5::AssetTypeNameByType(const asset_type_t assetType) +std::optional GameAssetPoolT5::AssetTypeNameByType(const asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent_v)) return ASSET_TYPE_NAMES[assetType]; - return ASSET_TYPE_INVALID; + return std::nullopt; } -const char* GameAssetPoolT5::GetAssetTypeName(const asset_type_t assetType) const +std::optional GameAssetPoolT5::GetAssetTypeName(const asset_type_t assetType) const { return AssetTypeNameByType(assetType); } diff --git a/src/ZoneCommon/Game/T5/GameAssetPoolT5.h b/src/ZoneCommon/Game/T5/GameAssetPoolT5.h index 27a2be3b..2d05eeed 100644 --- a/src/ZoneCommon/Game/T5/GameAssetPoolT5.h +++ b/src/ZoneCommon/Game/T5/GameAssetPoolT5.h @@ -58,8 +58,8 @@ public: _NODISCARD XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const override; - static const char* AssetTypeNameByType(asset_type_t assetType); - _NODISCARD const char* GetAssetTypeName(asset_type_t assetType) const override; + static std::optional AssetTypeNameByType(asset_type_t assetType); + _NODISCARD std::optional GetAssetTypeName(asset_type_t assetType) const override; static asset_type_t AssetTypeCount(); _NODISCARD asset_type_t GetAssetTypeCount() const override; diff --git a/src/ZoneCommon/Game/T6/AssetNameResolverT6.cpp b/src/ZoneCommon/Game/T6/AssetNameResolverT6.cpp new file mode 100644 index 00000000..765172d6 --- /dev/null +++ b/src/ZoneCommon/Game/T6/AssetNameResolverT6.cpp @@ -0,0 +1,22 @@ +#include "AssetNameResolverT6.h" + +#include "Game/T6/GameAssetPoolT6.h" +#include "Utils/StringUtils.h" + +using namespace T6; + +AssetNameResolver::AssetNameResolver() +{ + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + AddAssetTypeName(assetType, *GameAssetPoolT6::AssetTypeNameByType(assetType)); +} + +GameId AssetNameResolver::GetGameId() const +{ + return GameId::T6; +} + +std::optional AssetNameResolver::GetAssetTypeName(const asset_type_t assetType) const +{ + return GameAssetPoolT6::AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/T6/AssetNameResolverT6.h b/src/ZoneCommon/Game/T6/AssetNameResolverT6.h new file mode 100644 index 00000000..39cc1805 --- /dev/null +++ b/src/ZoneCommon/Game/T6/AssetNameResolverT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Zone/AssetNameResolver.h" + +namespace T6 +{ + class AssetNameResolver final : public HashMapBasedAssetNameResolver + { + public: + AssetNameResolver(); + [[nodiscard]] GameId GetGameId() const override; + [[nodiscard]] std::optional GetAssetTypeName(asset_type_t assetType) const override; + }; +} // namespace T6 diff --git a/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp b/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp index 78b7dbd1..558e85f4 100644 --- a/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp +++ b/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp @@ -366,15 +366,15 @@ XAssetInfoGeneric* GameAssetPoolT6::GetAsset(const asset_type_t type, const std: #undef CASE_GET_ASSET } -const char* GameAssetPoolT6::AssetTypeNameByType(const asset_type_t assetType) +std::optional GameAssetPoolT6::AssetTypeNameByType(const asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent_v)) return ASSET_TYPE_NAMES[assetType]; - return ASSET_TYPE_INVALID; + return std::nullopt; } -const char* GameAssetPoolT6::GetAssetTypeName(const asset_type_t assetType) const +std::optional GameAssetPoolT6::GetAssetTypeName(const asset_type_t assetType) const { return AssetTypeNameByType(assetType); } diff --git a/src/ZoneCommon/Game/T6/GameAssetPoolT6.h b/src/ZoneCommon/Game/T6/GameAssetPoolT6.h index 33ee416f..de7f756b 100644 --- a/src/ZoneCommon/Game/T6/GameAssetPoolT6.h +++ b/src/ZoneCommon/Game/T6/GameAssetPoolT6.h @@ -74,8 +74,8 @@ public: _NODISCARD XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const override; - static const char* AssetTypeNameByType(asset_type_t assetType); - _NODISCARD const char* GetAssetTypeName(asset_type_t assetType) const override; + static std::optional AssetTypeNameByType(asset_type_t assetType); + _NODISCARD std::optional GetAssetTypeName(asset_type_t assetType) const override; static asset_type_t AssetTypeCount(); _NODISCARD asset_type_t GetAssetTypeCount() const override; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp index 2ba2af5e..203ca22c 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp @@ -13,7 +13,7 @@ SequenceZoneDefinitionAssetList::SequenceZoneDefinitionAssetList() }); } -void SequenceZoneDefinitionAssetList::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionAssetList::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const { - state->m_asset_lists.emplace_back(result.NextCapture(CAPTURE_ASSET_LIST_NAME).FieldValue()); + state->m_definition->m_asset_lists.emplace_back(result.NextCapture(CAPTURE_ASSET_LIST_NAME).FieldValue()); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h index f9a336e4..245fc7b7 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h @@ -7,7 +7,7 @@ class SequenceZoneDefinitionAssetList final : public ZoneDefinitionParser::seque static constexpr auto CAPTURE_ASSET_LIST_NAME = 1; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; public: SequenceZoneDefinitionAssetList(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp index a7a11a08..bbae196b 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp @@ -13,7 +13,7 @@ SequenceZoneDefinitionBuild::SequenceZoneDefinitionBuild() }); } -void SequenceZoneDefinitionBuild::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionBuild::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const { - state->m_targets_to_build.emplace_back(result.NextCapture(CAPTURE_BUILD_TARGET_NAME).FieldValue()); + state->m_definition->m_targets_to_build.emplace_back(result.NextCapture(CAPTURE_BUILD_TARGET_NAME).FieldValue()); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h index 8e5b963b..ff965224 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h @@ -7,7 +7,7 @@ class SequenceZoneDefinitionBuild final : public ZoneDefinitionParser::sequence_ static constexpr auto CAPTURE_BUILD_TARGET_NAME = 1; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; public: SequenceZoneDefinitionBuild(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp index dbdb150e..d73fad05 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp @@ -19,19 +19,23 @@ SequenceZoneDefinitionEntry::SequenceZoneDefinitionEntry() }); } -void SequenceZoneDefinitionEntry::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionEntry::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const { - const auto& assetNameCapture = result.NextCapture(CAPTURE_ASSET_NAME); + const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE_NAME); + if (!state->m_asset_name_resolver) + throw ParsingException(typeNameToken.GetPos(), "Must define game before first asset"); + + const auto maybeAssetType = state->m_asset_name_resolver->GetAssetTypeByName(typeNameToken.FieldValue()); + if (!maybeAssetType) + throw ParsingException(typeNameToken.GetPos(), "Unknown asset type"); + + const auto& assetNameToken = result.NextCapture(CAPTURE_ASSET_NAME); std::string assetName; - if (assetNameCapture.m_type == ZoneDefinitionParserValueType::STRING) - { - assetName = assetNameCapture.StringValue(); - } + if (typeNameToken.m_type == ZoneDefinitionParserValueType::STRING) + assetName = typeNameToken.StringValue(); else - { - assetName = assetNameCapture.FieldValue(); - } + assetName = typeNameToken.FieldValue(); - state->m_assets.emplace_back(result.NextCapture(CAPTURE_TYPE_NAME).FieldValue(), assetName, result.NextTag() == TAG_REFERENCE); + state->m_definition->m_assets.emplace_back(*maybeAssetType, assetName, result.NextTag() == TAG_REFERENCE); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h index e9a6c44f..c88de4ee 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h @@ -10,7 +10,7 @@ class SequenceZoneDefinitionEntry final : public ZoneDefinitionParser::sequence_ static constexpr auto CAPTURE_ASSET_NAME = 2; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; public: SequenceZoneDefinitionEntry(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp index a6ea79af..19b5f59a 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp @@ -13,7 +13,7 @@ SequenceZoneDefinitionIgnore::SequenceZoneDefinitionIgnore() }); } -void SequenceZoneDefinitionIgnore::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionIgnore::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const { - state->m_ignores.emplace_back(result.NextCapture(CAPTURE_IGNORE_NAME).FieldValue()); + state->m_definition->m_ignores.emplace_back(result.NextCapture(CAPTURE_IGNORE_NAME).FieldValue()); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h index 9b258787..6fabb705 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h @@ -7,7 +7,7 @@ class SequenceZoneDefinitionIgnore final : public ZoneDefinitionParser::sequence static constexpr auto CAPTURE_IGNORE_NAME = 1; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; public: SequenceZoneDefinitionIgnore(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp index dda360f2..29488a86 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp @@ -13,7 +13,7 @@ SequenceZoneDefinitionInclude::SequenceZoneDefinitionInclude() }); } -void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const { - state->m_includes.emplace_back(result.NextCapture(CAPTURE_INCLUDE_NAME).FieldValue()); + state->m_definition->m_includes.emplace_back(result.NextCapture(CAPTURE_INCLUDE_NAME).FieldValue()); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h index a981bcba..09f85c17 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h @@ -7,7 +7,7 @@ class SequenceZoneDefinitionInclude final : public ZoneDefinitionParser::sequenc static constexpr auto CAPTURE_INCLUDE_NAME = 1; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; public: SequenceZoneDefinitionInclude(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp index 56e8cd3d..cb99bd30 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp @@ -1,6 +1,46 @@ #include "SequenceZoneDefinitionMetaData.h" #include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" +#include "Utils/StringUtils.h" + +#include +#include + +namespace +{ + constexpr auto METADATA_GAME = "game"; + constexpr auto METADATA_GDT = "gdt"; + constexpr auto METADATA_NAME = "name"; + constexpr auto METADATA_TYPE = "type"; + + std::optional GetGameByName(const std::string& gameName) + { + auto upperGameName = gameName; + utils::MakeStringUpperCase(upperGameName); + + for (auto i = 0u; i < static_cast(GameId::COUNT); i++) + { + if (upperGameName == GameId_Names[i]) + return static_cast(i); + } + + return std::nullopt; + } + + std::optional GetProjectTypeByName(const std::string& projectTypeName) + { + auto lowerProjectTypeName = projectTypeName; + utils::MakeStringLowerCase(lowerProjectTypeName); + + for (auto i = 0u; i < static_cast(ProjectType::COUNT); i++) + { + if (lowerProjectTypeName == ProjectType_Names[i]) + return static_cast(i); + } + + return std::nullopt; + } +} // namespace SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData() { @@ -14,7 +54,43 @@ SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData() }); } -void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinition* state, SequenceResult& result) const +void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const { - state->AddMetaData(result.NextCapture(CAPTURE_KEY).FieldValue(), result.NextCapture(CAPTURE_VALUE).FieldValue()); + const auto& keyToken = result.NextCapture(CAPTURE_KEY); + auto key = keyToken.FieldValue(); + const auto& valueToken = result.NextCapture(CAPTURE_VALUE); + const auto& value = valueToken.FieldValue(); + + utils::MakeStringLowerCase(key); + + if (key == METADATA_GAME) + { + const auto game = GetGameByName(value); + if (!game) + throw ParsingException(valueToken.GetPos(), "Unknown game name"); + + const auto previousGame = state->m_definition->m_game; + if (previousGame != GameId::COUNT && previousGame != *game) + throw ParsingException(valueToken.GetPos(), std::format("Game was previously defined as: {}", GameId_Names[static_cast(previousGame)])); + + state->SetGame(*game); + } + else if (key == METADATA_GDT) + { + state->m_definition->m_gdts.emplace_back(value); + } + else if (key == METADATA_NAME) + { + state->m_definition->m_name = value; + } + else if (key == METADATA_TYPE) + { + const auto projectType = GetProjectTypeByName(value); + if (!projectType) + throw ParsingException(valueToken.GetPos(), "Unknown project type name"); + } + else + { + state->m_definition->m_properties.AddProperty(key, value); + } } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h index efca91c2..bcb3b249 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h @@ -8,7 +8,7 @@ class SequenceZoneDefinitionMetaData final : public ZoneDefinitionParser::sequen static constexpr auto CAPTURE_VALUE = 2; protected: - void ProcessMatch(ZoneDefinition* state, SequenceResult& result) const override; + void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; public: SequenceZoneDefinitionMetaData(); diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp index 5ae6bfc2..eba6f2fb 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp @@ -7,12 +7,14 @@ #include "Sequence/SequenceZoneDefinitionInclude.h" #include "Sequence/SequenceZoneDefinitionMetaData.h" -ZoneDefinitionParser::ZoneDefinitionParser(ZoneDefinitionLexer* lexer) - : AbstractParser(lexer, std::make_unique()) +ZoneDefinitionParser::ZoneDefinitionParser(ZoneDefinitionLexer* lexer, const std::optional maybeGame) + : AbstractParser(lexer, std::make_unique()) { + if (maybeGame) + m_state->SetGame(*maybeGame); } -const std::vector::sequence_t*>& ZoneDefinitionParser::GetTestsForState() +const std::vector::sequence_t*>& ZoneDefinitionParser::GetTestsForState() { static std::vector tests({ new SequenceZoneDefinitionMetaData(), @@ -28,5 +30,5 @@ const std::vector::seq std::unique_ptr ZoneDefinitionParser::GetParsedValue() { - return std::move(m_state); + return std::move(m_state->m_definition); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h index b4a3099b..4ffffeee 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h @@ -1,16 +1,20 @@ #pragma once +#include "Game/IGame.h" #include "Parsing/Impl/AbstractParser.h" #include "Zone/Definition/ZoneDefinition.h" #include "ZoneDefinitionLexer.h" +#include "ZoneDefinitionParserState.h" #include "ZoneDefinitionParserValue.h" -class ZoneDefinitionParser final : public AbstractParser +#include + +class ZoneDefinitionParser final : public AbstractParser { protected: const std::vector& GetTestsForState() override; public: - explicit ZoneDefinitionParser(ZoneDefinitionLexer* lexer); + explicit ZoneDefinitionParser(ZoneDefinitionLexer* lexer, std::optional maybeGame = std::nullopt); std::unique_ptr GetParsedValue(); }; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.cpp new file mode 100644 index 00000000..54dffc88 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.cpp @@ -0,0 +1,13 @@ +#include "ZoneDefinitionParserState.h" + +ZoneDefinitionParserState::ZoneDefinitionParserState() + : m_asset_name_resolver(nullptr), + m_definition(std::make_unique()) +{ +} + +void ZoneDefinitionParserState::SetGame(const GameId game) +{ + m_definition->m_game = game; + m_asset_name_resolver = IAssetNameResolver::GetResolverForGame(game); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.h b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.h new file mode 100644 index 00000000..80074879 --- /dev/null +++ b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Zone/AssetNameResolver.h" +#include "Zone/Definition/ZoneDefinition.h" + +#include + +class ZoneDefinitionParserState +{ +public: + ZoneDefinitionParserState(); + + void SetGame(GameId game); + + const IAssetNameResolver* m_asset_name_resolver; + std::unique_ptr m_definition; +}; diff --git a/src/ZoneCommon/Pool/ZoneAssetPools.h b/src/ZoneCommon/Pool/ZoneAssetPools.h index d3bf72d8..9f6876e0 100644 --- a/src/ZoneCommon/Pool/ZoneAssetPools.h +++ b/src/ZoneCommon/Pool/ZoneAssetPools.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -42,7 +43,7 @@ public: _NODISCARD virtual XAssetInfoGeneric* GetAssetOrAssetReference(asset_type_t type, const std::string& name) const; _NODISCARD virtual asset_type_t GetAssetTypeCount() const = 0; - _NODISCARD virtual const char* GetAssetTypeName(asset_type_t assetType) const = 0; + _NODISCARD virtual std::optional GetAssetTypeName(asset_type_t assetType) const = 0; virtual void InitPoolStatic(asset_type_t type, size_t capacity) = 0; virtual void InitPoolDynamic(asset_type_t type) = 0; diff --git a/src/ZoneCommon/Zone/AssetList/AssetList.cpp b/src/ZoneCommon/Zone/AssetList/AssetList.cpp index 05a13562..4c5f956a 100644 --- a/src/ZoneCommon/Zone/AssetList/AssetList.cpp +++ b/src/ZoneCommon/Zone/AssetList/AssetList.cpp @@ -1,12 +1,13 @@ #include "AssetList.h" AssetListEntry::AssetListEntry() - : m_is_reference(false) + : m_type(0u), + m_is_reference(false) { } -AssetListEntry::AssetListEntry(std::string type, std::string name, const bool isReference) - : m_type(std::move(type)), +AssetListEntry::AssetListEntry(const asset_type_t type, std::string name, const bool isReference) + : m_type(type), m_name(std::move(name)), m_is_reference(isReference) { diff --git a/src/ZoneCommon/Zone/AssetList/AssetList.h b/src/ZoneCommon/Zone/AssetList/AssetList.h index 56178a29..68e9fa2c 100644 --- a/src/ZoneCommon/Zone/AssetList/AssetList.h +++ b/src/ZoneCommon/Zone/AssetList/AssetList.h @@ -1,16 +1,19 @@ #pragma once + +#include "Zone/ZoneTypes.h" + #include #include class AssetListEntry { public: - std::string m_type; + asset_type_t m_type; std::string m_name; bool m_is_reference; AssetListEntry(); - AssetListEntry(std::string type, std::string name, bool isReference); + AssetListEntry(asset_type_t type, std::string name, bool isReference); }; class AssetList diff --git a/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp b/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp index 546ec169..2615ca92 100644 --- a/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp +++ b/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp @@ -1,13 +1,18 @@ #include "AssetListStream.h" -AssetListInputStream::AssetListInputStream(std::istream& stream) - : m_stream(stream) +#include + +AssetListInputStream::AssetListInputStream(std::istream& stream, const GameId game) + : m_stream(stream), + m_asset_name_resolver(IAssetNameResolver::GetResolverForGame(game)) { } -bool AssetListInputStream::NextEntry(AssetListEntry& entry) const +bool AssetListInputStream::NextEntry(AssetListEntry& entry, bool* failure) const { std::vector row; + if (failure) + *failure = false; while (true) { @@ -17,7 +22,17 @@ bool AssetListInputStream::NextEntry(AssetListEntry& entry) const if (row.empty()) continue; - entry.m_type = row[0]; + const auto& typeName = row[0]; + const auto maybeType = m_asset_name_resolver->GetAssetTypeByName(typeName); + if (!maybeType) + { + std::cerr << std::format("Unknown asset type name \"{}\"\n", typeName); + if (failure) + *failure = true; + return false; + } + + entry.m_type = *maybeType; if (row.size() >= 3 && row[1].empty()) { entry.m_name = row[2]; @@ -33,14 +48,15 @@ bool AssetListInputStream::NextEntry(AssetListEntry& entry) const } } -AssetListOutputStream::AssetListOutputStream(std::ostream& stream) - : m_stream(stream) +AssetListOutputStream::AssetListOutputStream(std::ostream& stream, const GameId game) + : m_stream(stream), + m_asset_name_resolver(IAssetNameResolver::GetResolverForGame(game)) { } void AssetListOutputStream::WriteEntry(const AssetListEntry& entry) { - m_stream.WriteColumn(entry.m_type); + m_stream.WriteColumn(*m_asset_name_resolver->GetAssetTypeName(entry.m_type)); m_stream.WriteColumn(entry.m_name); m_stream.NextRow(); } diff --git a/src/ZoneCommon/Zone/AssetList/AssetListStream.h b/src/ZoneCommon/Zone/AssetList/AssetListStream.h index 634bee97..da16def6 100644 --- a/src/ZoneCommon/Zone/AssetList/AssetListStream.h +++ b/src/ZoneCommon/Zone/AssetList/AssetListStream.h @@ -1,25 +1,31 @@ #pragma once #include "AssetList.h" #include "Csv/CsvStream.h" +#include "Game/IGame.h" +#include #include class AssetListInputStream { - CsvInputStream m_stream; - public: - explicit AssetListInputStream(std::istream& stream); + AssetListInputStream(std::istream& stream, GameId game); - bool NextEntry(AssetListEntry& entry) const; + bool NextEntry(AssetListEntry& entry, bool* failure) const; + +private: + CsvInputStream m_stream; + const IAssetNameResolver* m_asset_name_resolver; }; class AssetListOutputStream { - CsvOutputStream m_stream; - public: - explicit AssetListOutputStream(std::ostream& stream); + AssetListOutputStream(std::ostream& stream, GameId game); void WriteEntry(const AssetListEntry& entry); + +private: + CsvOutputStream m_stream; + const IAssetNameResolver* m_asset_name_resolver; }; diff --git a/src/ZoneCommon/Zone/AssetNameResolver.cpp b/src/ZoneCommon/Zone/AssetNameResolver.cpp new file mode 100644 index 00000000..6b2ee715 --- /dev/null +++ b/src/ZoneCommon/Zone/AssetNameResolver.cpp @@ -0,0 +1,45 @@ +#include "AssetNameResolver.h" + +#include "Game/IW3/AssetNameResolverIW3.h" +#include "Game/IW4/AssetNameResolverIW4.h" +#include "Game/IW5/AssetNameResolverIW5.h" +#include "Game/T5/AssetNameResolverT5.h" +#include "Game/T6/AssetNameResolverT6.h" +#include "Utils/StringUtils.h" + +#include + +const IAssetNameResolver* IAssetNameResolver::GetResolverForGame(GameId game) +{ + static const IAssetNameResolver* assetNameResolvers[static_cast(GameId::COUNT)]{ + new IW3::AssetNameResolver(), + new IW4::AssetNameResolver(), + new IW5::AssetNameResolver(), + new T5::AssetNameResolver(), + new T6::AssetNameResolver(), + }; + + assert(static_cast(game) < static_cast(GameId::COUNT)); + const auto* result = assetNameResolvers[static_cast(game)]; + assert(result); + + return result; +} + +void HashMapBasedAssetNameResolver::AddAssetTypeName(asset_type_t assetType, std::string name) +{ + utils::MakeStringLowerCase(name); + m_asset_types_by_name.emplace(std::move(name), assetType); +} + +std::optional HashMapBasedAssetNameResolver::GetAssetTypeByName(const std::string& assetTypeName) const +{ + std::string lowerCaseName = assetTypeName; + utils::MakeStringLowerCase(lowerCaseName); + + const auto existingAssetType = m_asset_types_by_name.find(assetTypeName); + if (existingAssetType != m_asset_types_by_name.end()) + return existingAssetType->second; + + return std::nullopt; +} diff --git a/src/ZoneCommon/Zone/AssetNameResolver.h b/src/ZoneCommon/Zone/AssetNameResolver.h new file mode 100644 index 00000000..659479a4 --- /dev/null +++ b/src/ZoneCommon/Zone/AssetNameResolver.h @@ -0,0 +1,37 @@ +#pragma once + +#include "Game/IGame.h" +#include "Zone/ZoneTypes.h" + +#include +#include +#include + +class IAssetNameResolver +{ +public: + IAssetNameResolver() = default; + virtual ~IAssetNameResolver() = default; + IAssetNameResolver(const IAssetNameResolver& other) = default; + IAssetNameResolver(IAssetNameResolver&& other) noexcept = default; + IAssetNameResolver& operator=(const IAssetNameResolver& other) = default; + IAssetNameResolver& operator=(IAssetNameResolver&& other) noexcept = default; + + [[nodiscard]] virtual GameId GetGameId() const = 0; + [[nodiscard]] virtual std::optional GetAssetTypeByName(const std::string& assetTypeName) const = 0; + [[nodiscard]] virtual std::optional GetAssetTypeName(asset_type_t assetType) const = 0; + + static const IAssetNameResolver* GetResolverForGame(GameId game); +}; + +class HashMapBasedAssetNameResolver : public IAssetNameResolver +{ +public: + [[nodiscard]] std::optional GetAssetTypeByName(const std::string& assetTypeName) const override; + +protected: + void AddAssetTypeName(asset_type_t assetType, std::string name); + +private: + std::unordered_map m_asset_types_by_name; +}; diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp b/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp index 068f86f7..ee36f59b 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp @@ -1,55 +1,44 @@ #include "ZoneDefinition.h" -ZoneDefinitionEntry::ZoneDefinitionEntry() - : m_is_reference(false) -{ -} - -ZoneDefinitionEntry::ZoneDefinitionEntry(std::string type, std::string name, const bool isReference) - : m_asset_type(std::move(type)), +ZoneDefinitionAsset::ZoneDefinitionAsset(const asset_type_t type, std::string name, const bool isReference) + : m_asset_type(type), m_asset_name(std::move(name)), m_is_reference(isReference) { } -ZoneMetaDataEntry::ZoneMetaDataEntry() = default; +ZoneDefinitionProperties::ZoneDefinitionProperties() = default; -ZoneMetaDataEntry::ZoneMetaDataEntry(std::string key, std::string value) - : m_key(std::move(key)), - m_value(std::move(value)) +void ZoneDefinitionProperties::AddProperty(std::string key, std::string value) { + m_properties.emplace(std::move(key), std::move(value)); } -void ZoneDefinition::AddMetaData(std::string key, std::string value) +void ZoneDefinitionProperties::Include(const ZoneDefinitionProperties& otherProperties) +{ + for (const auto& property : otherProperties.m_properties) + AddProperty(property.first, property.second); +} + +ZoneDefinition::ZoneDefinition() + : m_type(ProjectType::NONE), + m_game(GameId::COUNT) { - auto metaData = std::make_unique(std::move(key), std::move(value)); - auto* metaDataPtr = metaData.get(); - m_metadata.emplace_back(std::move(metaData)); - m_metadata_lookup.emplace(std::make_pair(metaDataPtr->m_key, metaDataPtr)); } void ZoneDefinition::Include(const AssetList& assetListToInclude) { for (const auto& entry : assetListToInclude.m_entries) - { m_assets.emplace_back(entry.m_type, entry.m_name, false); - } } void ZoneDefinition::Include(const ZoneDefinition& definitionToInclude) { - for (const auto& metaData : definitionToInclude.m_metadata) - { - AddMetaData(metaData->m_key, metaData->m_value); - } + m_properties.Include(definitionToInclude.m_properties); for (const auto& ignore : definitionToInclude.m_ignores) - { m_ignores.emplace_back(ignore); - } for (const auto& asset : definitionToInclude.m_assets) - { m_assets.emplace_back(asset); - } } diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinition.h b/src/ZoneCommon/Zone/Definition/ZoneDefinition.h index 64514cfd..08b1a1df 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinition.h +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinition.h @@ -1,46 +1,66 @@ #pragma once +#include "Game/IGame.h" #include "Zone/AssetList/AssetList.h" +#include "Zone/ZoneTypes.h" -#include #include #include #include -class ZoneDefinitionEntry +enum class ProjectType { -public: - std::string m_asset_type; - std::string m_asset_name; - bool m_is_reference; + NONE, + FASTFILE, + IPAK, - ZoneDefinitionEntry(); - ZoneDefinitionEntry(std::string type, std::string name, bool isReference); + COUNT }; -class ZoneMetaDataEntry +static constexpr const char* ProjectType_Names[]{ + "none", + "fastfile", + "ipak", +}; +static_assert(std::extent_v == static_cast(ProjectType::COUNT)); + +class ZoneDefinitionAsset { public: - std::string m_key; - std::string m_value; + ZoneDefinitionAsset(asset_type_t type, std::string name, bool isReference); - ZoneMetaDataEntry(); - ZoneMetaDataEntry(std::string key, std::string value); + asset_type_t m_asset_type; + std::string m_asset_name; + bool m_is_reference; +}; + +class ZoneDefinitionProperties +{ +public: + ZoneDefinitionProperties(); + + void AddProperty(std::string key, std::string value); + void Include(const ZoneDefinitionProperties& otherProperties); + + std::unordered_map m_properties; }; class ZoneDefinition { public: + ZoneDefinition(); + + void Include(const AssetList& assetListToInclude); + void Include(const ZoneDefinition& definitionToInclude); + std::string m_name; - std::vector> m_metadata; - std::unordered_multimap m_metadata_lookup; + ProjectType m_type; + GameId m_game; + ZoneDefinitionProperties m_properties; std::vector m_includes; std::vector m_asset_lists; std::vector m_ignores; std::vector m_targets_to_build; - std::vector m_assets; - - void AddMetaData(std::string key, std::string value); - void Include(const AssetList& assetListToInclude); - void Include(const ZoneDefinition& definitionToInclude); + std::vector m_gdts; + std::vector m_assets; }; diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp index 7c763d14..72a34c8e 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp @@ -1,18 +1,19 @@ #include "ZoneDefinitionStream.h" +#include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/DefinesStreamProxy.h" #include "Parsing/Impl/ParserSingleInputStream.h" -#include "Parsing/Simple/SimpleLexer.h" #include "Parsing/ZoneDefinition/ZoneDefinitionLexer.h" #include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" -#include #include +#include ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream, std::string fileName, bool verbose) : m_file_name(std::move(fileName)), m_verbose(verbose), - m_stream(nullptr) + m_stream(nullptr), + m_previously_set_game(std::nullopt) { OpenBaseStream(stream); SetupStreamProxies(); @@ -29,21 +30,23 @@ void ZoneDefinitionInputStream::SetupStreamProxies() { m_open_streams.emplace_back(std::make_unique(m_open_streams.back().get())); auto definesProxy = std::make_unique(m_open_streams.back().get()); - definesProxy->AddDefine(DefinesStreamProxy::Define(ZONE_CODE_GENERATOR_DEFINE_NAME, ZONE_CODE_GENERATOR_DEFINE_VALUE)); m_open_streams.emplace_back(std::move(definesProxy)); m_stream = m_open_streams.back().get(); } +void ZoneDefinitionInputStream::SetPreviouslySetGame(GameId game) +{ + m_previously_set_game = game; +} + std::unique_ptr ZoneDefinitionInputStream::ReadDefinition() { if (m_verbose) - { - std::cout << "Reading zone definition file: " << m_file_name << "\n"; - } + std::cout << std::format("Reading zone definition file: {}\n", m_file_name); const auto lexer = std::make_unique(m_stream); - const auto parser = std::make_unique(lexer.get()); + const auto parser = std::make_unique(lexer.get(), m_previously_set_game); const auto start = std::chrono::steady_clock::now(); std::unique_ptr definition; @@ -52,9 +55,7 @@ std::unique_ptr ZoneDefinitionInputStream::ReadDefinition() const auto end = std::chrono::steady_clock::now(); if (m_verbose) - { - std::cout << "Processing zone definition took " << std::chrono::duration_cast(end - start).count() << "ms\n"; - } + std::cout << std::format("Processing zone definition took {}ms\n", std::chrono::duration_cast(end - start).count()); return std::move(definition); } diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h index 25723c18..b0b26984 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h @@ -1,33 +1,34 @@ #pragma once + +#include "Game/IGame.h" #include "Parsing/IParserLineStream.h" #include "ZoneDefinition.h" #include #include +#include class ZoneDefinitionInputStream { - static constexpr const char* ZONE_CODE_GENERATOR_DEFINE_NAME = "__zonecodegenerator"; - static constexpr const char* ZONE_CODE_GENERATOR_DEFINE_VALUE = "1"; +public: + ZoneDefinitionInputStream(std::istream& stream, std::string fileName, bool verbose); + + void SetPreviouslySetGame(GameId game); + std::unique_ptr ReadDefinition(); + +private: + bool OpenBaseStream(std::istream& stream); + void SetupStreamProxies(); std::string m_file_name; bool m_verbose; IParserLineStream* m_stream; std::vector> m_open_streams; - - bool OpenBaseStream(std::istream& stream); - void SetupStreamProxies(); - -public: - ZoneDefinitionInputStream(std::istream& stream, std::string fileName, bool verbose); - - std::unique_ptr ReadDefinition(); + std::optional m_previously_set_game; }; class ZoneDefinitionOutputStream { - std::ostream& m_stream; - public: explicit ZoneDefinitionOutputStream(std::ostream& stream); @@ -35,4 +36,7 @@ public: void WriteComment(const std::string& comment) const; void WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const; void WriteEntry(const std::string& entryKey, const std::string& entryValue) const; + +private: + std::ostream& m_stream; };